<commit_before>var Akismet = require('akismet'),
    Honeypot = require('project-honeypot'),
    simpleRecaptcha = require('simple-recaptcha'),
    pluginData = require('./plugin.json'),
    winston = module.parent.require('winston'),
    nconf = module.parent.require('nconf'),
    async = module.parent.require('async'),
    Meta = module.parent.require('./meta'),
    user = module.parent.require('./user'),
    topics = module.parent.require('./topics'),
    db = module.parent.require('./database'),
    akismet, honeypot, recaptchaArgs, pluginSettings,
    Plugin = {};

pluginData.nbbId = pluginData.id.replace(/nodebb-plugin-/, '');

var util = {
    keys: function(obj, props, value) {
        if(props == null || obj == null)
            return undefined;

        var i = props.indexOf(".");
        if( i == -1 ) {
            if(value !== undefined)
                obj[props] = value;
            return obj[props];
        }
        var prop = props.slice(0, i),
            newProps = props.slice(i + 1);

        if(props !== undefined && !(obj[prop] instanceof Object) )
            obj[prop] = {};

        return util.keys(obj[prop], newProps, value);
    }
};

Plugin.load = function(params, callback) {

    var render = function(req, res, next) {
        res.render('admin/plugins/' + pluginData.nbbId, pluginData || {});
    };

    Meta.settings.get(pluginData.nbbId, function(err, settings) {
        if (!err && settings) {
            if (settings.akismetEnabled === 'on') {
                if (settings.akismetApiKey) {
                    akismet = require('akismet').client({blog: nconf.get('url'), apiKey: settings.akismetApiKey});
                    akismet.verifyKey(function(err, verified) {
                        if (!verified) {
                            winston.error('[plugins/' + pluginData.nbbId + '] Unable to verify Akismet API key.');
                            akismet = null;
                        }
                    });
                } else {
                    winston.error('[plugins/' + pluginData.nbbId + '] Akismet API Key not set!');
                }
            }

            if (settings.honeypotEnabled === 'on') {
                if (settings.honeypotApiKey) {
                    honeypot = Honeypot(settings.honeypotApiKey)
                } else {
                    winston.error('[plugins/' + pluginData.nbbId + '] Honeypot API Key not set!');
                }
            }

            if (settings.recaptchaEnabled === 'on') {
                if (settings.recaptchaPublicKey && settings.recaptchaPrivateKey ) {
                    var recaptchaLanguages = {'en': 1, 'nl': 1, 'fr': 1, 'de': 1, 'pt': 1, 'ru': 1, 'es': 1, 'tr': 1},
                        lang = (Meta.config.defaultLang || 'en').toLowerCase();

                    recaptchaArgs = {
                        publicKey: settings.recaptchaPublicKey,
                        targetId: pluginData.nbbId + '-recaptcha-target',
                        options: {
                            // theme: settings.recaptchaTheme || 'clean',
                            //todo: switch to custom theme, issue#9
                            theme: 'clean',
                            lang: recaptchaLanguages[lang] ? lang : 'en',
                            tabindex: settings.recaptchaTabindex || 0
                        }
                    };
                }
            } else {
                recaptchaArgs = null;
            }
            winston.info('[plugins/' + pluginData.nbbId + '] Settings loaded');
            pluginSettings = settings;
        } else {
            winston.warn('[plugins/' + pluginData.nbbId + '] Settings not set or could not be retrived!');
        }

        params.router.get('/admin/plugins/' + pluginData.nbbId, params.middleware.admin.buildHeader, render);
        params.router.get('/api/admin/plugins/' + pluginData.nbbId, render);

        if (typeof callback === 'function') {
            callback();
        }
    });
};

Plugin.addCaptcha = function(data, callback) {
    if (recaptchaArgs) {
        var captcha = {
            label: 'Captcha',
            html: ''
                + '

'
                + '',
            styleName: pluginData.nbbId
        };
        if (data.templateData.regFormEntry && Array.isArray(data.templateData.regFormEntry)) {
            data.templateData.regFormEntry.push(captcha);
        } else {
            data.templateData.captcha = captcha;
        }
    }
    callback(null, data);
};

Plugin.checkReply = function(data, callback) {
    // http://akismet.com/development/api/#comment-check
    if (!akismet || !data.req) {
        return callback(null, data);
    }

    user.getUserField(data.uid, 'username', function(err, username) {
        if (err) {
            return callback(err);
        }

        akismet.checkSpam({
            user_ip: data.req.ip,
            user_agent: data.req.headers['user-agent'],
            blog: data.req.protocol + '://' + data.req.host,
            permalink: data.req.path,
            comment_content: (data.title ? data.title + '\n\n' : '') + (data.content || ''),
            comment_author: username
        }, function(err, spam) {
            if (err || !spam) {
                return callback(err, data);
            }

            winston.warn('[plugins/' + pluginData.nbbId + '] Post "' + data.content + '" by uid: ' + data.uid + ' username: '+ username + '@' + data.req.ip + ' was flagged as spam and rejected.');
            callback(new Error('Post content was flagged as spam by Akismet.com'), data);
        });
    });
};

Plugin.checkRegister = function(data, callback) {
    async.parallel([
        function(next) {
            Plugin._honeypotCheck(data.req, data.res, data.userData, next);
        },
        function(next) {
            Plugin._recaptchaCheck(data.req, data.res, data.userData, next)
        }
    ], function(err, results) {
        callback(err, data);
    });
};

Plugin.onPostFlagged = function(flagged) {
    if (akismet && pluginSettings.akismetFlagReporting && parseInt(flagged.flaggingUser.reputation, 10) >= parseInt(pluginSettings.akismetFlagReporting, 10)) {
        async.parallel({
            comment_author: function(next) {
                user.getUserField(flagged.post.uid, 'username', next);
            },
            permalink: function(next) {
                topics.getTopicField(flagged.post.tid, 'slug', next);
            },
            ip: function(next) {
                db.getSortedSetRevRange('uid:' + flagged.post.uid + ':ip', 0, 1, next);
            }
        }, function(err, data) {
            var submitted = {
                user_ip: data.ip ? data.ip[0] : '',
                permalink: nconf.get('url').replace(/\/$/, '') + '/topic/' + data.permalink,
                comment_author: data.comment_author,
                comment_content: flagged.post.content
            };

            akismet.submitSpam(submitted, function(err) {
                console.log('Spam reported to Akismet.', submitted);
            });
        });
    }
};

Plugin._honeypotCheck = function(req, res, userData, next) {
    if (honeypot && req && req.ip) {
        honeypot.query(req.ip, function (err, results) {
            if (err) {
                winston.error(err);
                next(null, userData);
            } else {
                if (results && results.found && results.type) {
                    if (results.type.spammer || results.type.suspicious) {
                        var message = userData.username + ' | ' + userData.email + ' was detected as ' +  (results.type.spammer ? 'spammer' : 'suspicious');

                        winston.warn('[plugins/' + pluginData.nbbId + '] ' + message + ' and was denied registration.');
                        next(new Error(message), userData);
                    } else {
                        next(null, userData);
                    }
                } else {
                    winston.warn('[plugins/' + pluginData.nbbId + '] username:' + userData.username + ' ip:' + req.ip + ' was not found in Honeypot database');
                    next(null, userData);
                }
            }
        });
    } else {
        next(null, userData);
    }
};

Plugin._recaptchaCheck = function(req, res, userData, next) {
    if (recaptchaArgs && req && req.ip && req.body) {

        simpleRecaptcha(
            pluginSettings.recaptchaPrivateKey,
            req.ip,
            req.body['g-recaptcha-response'],
            function(err) {
                if (err) {
                    var message = err.Error || 'Captcha not verified, are you a robot?';
                    winston.warn('[plugins/' + pluginData.nbbId + '] ' + message);
                    next(new Error(message), userData);
                } else {
                    next(null, userData);
                }
            }
        );
    } else {
        next(null, userData);
    }
};

Plugin.admin = {
    menu: function(custom_header, callback) {
        custom_header.plugins.push({
            "route": '/plugins/' + pluginData.nbbId,
            "icon": pluginData.faIcon,
            "name": pluginData.name
        });

        callback(null, custom_header);
    }
};

module.exports = Plugin;
<commit_msg>related to #44<commit_after>var Akismet = require('akismet'),
    Honeypot = require('project-honeypot'),
    simpleRecaptcha = require('simple-recaptcha'),
    pluginData = require('./plugin.json'),
    winston = module.parent.require('winston'),
    nconf = module.parent.require('nconf'),
    async = module.parent.require('async'),
    Meta = module.parent.require('./meta'),
    user = module.parent.require('./user'),
    topics = module.parent.require('./topics'),
    db = module.parent.require('./database'),
    akismet, honeypot, recaptchaArgs, pluginSettings,
    Plugin = {};

pluginData.nbbId = pluginData.id.replace(/nodebb-plugin-/, '');

var util = {
    keys: function(obj, props, value) {
        if(props == null || obj == null)
            return undefined;

        var i = props.indexOf(".");
        if( i == -1 ) {
            if(value !== undefined)
                obj[props] = value;
            return obj[props];
        }
        var prop = props.slice(0, i),
            newProps = props.slice(i + 1);

        if(props !== undefined && !(obj[prop] instanceof Object) )
            obj[prop] = {};

        return util.keys(obj[prop], newProps, value);
    }
};

Plugin.load = function(params, callback) {

    var render = function(req, res, next) {
        res.render('admin/plugins/' + pluginData.nbbId, pluginData || {});
    };

    Meta.settings.get(pluginData.nbbId, function(err, settings) {
        if (!err && settings) {
            if (settings.akismetEnabled === 'on') {
                if (settings.akismetApiKey) {
                    akismet = require('akismet').client({blog: nconf.get('url'), apiKey: settings.akismetApiKey});
                    akismet.verifyKey(function(err, verified) {
                        if (!verified) {
                            winston.error('[plugins/' + pluginData.nbbId + '] Unable to verify Akismet API key.');
                            akismet = null;
                        }
                    });
                } else {
                    winston.error('[plugins/' + pluginData.nbbId + '] Akismet API Key not set!');
                }
            }

            if (settings.honeypotEnabled === 'on') {
                if (settings.honeypotApiKey) {
                    honeypot = Honeypot(settings.honeypotApiKey)
                } else {
                    winston.error('[plugins/' + pluginData.nbbId + '] Honeypot API Key not set!');
                }
            }

            if (settings.recaptchaEnabled === 'on') {
                if (settings.recaptchaPublicKey && settings.recaptchaPrivateKey ) {
                    var recaptchaLanguages = {'en': 1, 'nl': 1, 'fr': 1, 'de': 1, 'pt': 1, 'ru': 1, 'es': 1, 'tr': 1},
                        lang = (Meta.config.defaultLang || 'en').toLowerCase();

                    recaptchaArgs = {
                        publicKey: settings.recaptchaPublicKey,
                        targetId: pluginData.nbbId + '-recaptcha-target',
                        options: {
                            // theme: settings.recaptchaTheme || 'clean',
                            //todo: switch to custom theme, issue#9
                            theme: 'clean',
                            lang: recaptchaLanguages[lang] ? lang : 'en',
                            tabindex: settings.recaptchaTabindex || 0
                        }
                    };
                }
            } else {
                recaptchaArgs = null;
            }
            winston.info('[plugins/' + pluginData.nbbId + '] Settings loaded');
            pluginSettings = settings;
        } else {
            winston.warn('[plugins/' + pluginData.nbbId + '] Settings not set or could not be retrived!');
        }

        params.router.get('/admin/plugins/' + pluginData.nbbId, params.middleware.admin.buildHeader, render);
        params.router.get('/api/admin/plugins/' + pluginData.nbbId, render);

        if (typeof callback === 'function') {
            callback();
        }
    });
};

Plugin.addCaptcha = function(data, callback) {
    if (recaptchaArgs) {
        var captcha = {
            label: 'Captcha',
            html: ''
                + '

'
                + '',
            styleName: pluginData.nbbId
        };
        if (data.templateData.regFormEntry && Array.isArray(data.templateData.regFormEntry)) {
            data.templateData.regFormEntry.push(captcha);
        } else {
            data.templateData.captcha = captcha;
        }
    }
    callback(null, data);
};

Plugin.checkReply = function(data, callback) {
    // http://akismet.com/development/api/#comment-check
    if (!akismet || !data.req) {
        return callback(null, data);
    }

    user.getUserField(data.uid, 'username', function(err, username) {
        if (err) {
            return callback(err);
        }

        akismet.checkSpam({
            user_ip: data.req.ip,
            user_agent: data.req.headers['user-agent'],
            permalink: nconf.get('url').replace(/\/$/, '') + data.req.path,
            comment_content: (data.title ? data.title + '\n\n' : '') + (data.content || ''),
            comment_author: username
        }, function(err, spam) {
            if (err || !spam) {
                return callback(err, data);
            }

            winston.warn('[plugins/' + pluginData.nbbId + '] Post "' + data.content + '" by uid: ' + data.uid + ' username: '+ username + '@' + data.req.ip + ' was flagged as spam and rejected.');
            callback(new Error('Post content was flagged as spam by Akismet.com'), data);
        });
    });
};

Plugin.checkRegister = function(data, callback) {
    async.parallel([
        function(next) {
            Plugin._honeypotCheck(data.req, data.res, data.userData, next);
        },
        function(next) {
            Plugin._recaptchaCheck(data.req, data.res, data.userData, next)
        }
    ], function(err, results) {
        callback(err, data);
    });
};

Plugin.onPostFlagged = function(flagged) {
    if (akismet && pluginSettings.akismetFlagReporting && parseInt(flagged.flaggingUser.reputation, 10) >= parseInt(pluginSettings.akismetFlagReporting, 10)) {
        async.parallel({
            comment_author: function(next) {
                user.getUserField(flagged.post.uid, 'username', next);
            },
            permalink: function(next) {
                topics.getTopicField(flagged.post.tid, 'slug', next);
            },
            ip: function(next) {
                db.getSortedSetRevRange('uid:' + flagged.post.uid + ':ip', 0, 1, next);
            }
        }, function(err, data) {
            var submitted = {
                user_ip: data.ip ? data.ip[0] : '',
                permalink: nconf.get('url').replace(/\/$/, '') + '/topic/' + data.permalink,
                comment_author: data.comment_author,
                comment_content: flagged.post.content
            };

            akismet.submitSpam(submitted, function(err) {
                if (err) winston.error('Error reporting to Akismet', err, submitted);

                winston.info('Spam reported to Akismet.', submitted);
            });
        });
    }
};

Plugin._honeypotCheck = function(req, res, userData, next) {
    if (honeypot && req && req.ip) {
        honeypot.query(req.ip, function (err, results) {
            if (err) {
                winston.error(err);
                next(null, userData);
            } else {
                if (results && results.found && results.type) {
                    if (results.type.spammer || results.type.suspicious) {
                        var message = userData.username + ' | ' + userData.email + ' was detected as ' +  (results.type.spammer ? 'spammer' : 'suspicious');

                        winston.warn('[plugins/' + pluginData.nbbId + '] ' + message + ' and was denied registration.');
                        next(new Error(message), userData);
                    } else {
                        next(null, userData);
                    }
                } else {
                    winston.warn('[plugins/' + pluginData.nbbId + '] username:' + userData.username + ' ip:' + req.ip + ' was not found in Honeypot database');
                    next(null, userData);
                }
            }
        });
    } else {
        next(null, userData);
    }
};

Plugin._recaptchaCheck = function(req, res, userData, next) {
    if (recaptchaArgs && req && req.ip && req.body) {

        simpleRecaptcha(
            pluginSettings.recaptchaPrivateKey,
            req.ip,
            req.body['g-recaptcha-response'],
            function(err) {
                if (err) {
                    var message = err.Error || 'Captcha not verified, are you a robot?';
                    winston.warn('[plugins/' + pluginData.nbbId + '] ' + message);
                    next(new Error(message), userData);
                } else {
                    next(null, userData);
                }
            }
        );
    } else {
        next(null, userData);
    }
};

Plugin.admin = {
    menu: function(custom_header, callback) {
        custom_header.plugins.push({
            "route": '/plugins/' + pluginData.nbbId,
            "icon": pluginData.faIcon,
            "name": pluginData.name
        });

        callback(null, custom_header);
    }
};

module.exports = Plugin;
<|endoftext|>


<commit_before>'use strict';

var meta = module.parent.require('./meta');
var user = module.parent.require('./user');
var nconf = require('nconf');

var db = module.parent.require('./database'); // NodeBB / src / database 참고.
var au = module.parent.require('./controllers/authentication'); // NodeBB / src / controllers 참고.

var winston = require('winston');
// 모듈 객체.
var plugin = {};

plugin.init = function (params, callback)	{
	var router = params.router;

	winston.info('Start community..');

	router.get('/community', function ()	{
		console.log(arguments);
	});

	callback();
}

plugin.verifyUser = function (token, callback)	{

}

// 이 함수는 NodeBB 에서 어떤 동작 또는 페이지이동 때마다 호출되므로 계속해서 토큰을 받아오고 유저 유효성 검사를 할 것이다.
// 그러므로 함수 첫줄에 세션 확인을 하는 구문을 만들어 같은 세션일 경우 유저 유효성 검사를 넘어가도록 한다.
plugin.addMiddleware = function (req, res, next)	{
	nconf.set('mongo:database', 'biobank-session');
	var newdb = nconf.get('mongo:database');

	db.info(newdb, function ()	{
		console.log(arguments);
	})
	console.log('login add middle ware!!', req.headers.cookie);
	// 이미 있는 세션일 경우 요청 프로퍼티에 user 와 user 안에 uid 가 존재 한다.
	// TODO.
	// 로그아웃 후 창을 닫고 바이오클라우드에서 다시 커뮤니티로 접속하면 세션관련 리프레쉬가 발생한다.
	// 이 경우 세션이 변경됨을 확인하고 리프레쉬를 해줘야한다.
	var hasSession = req.hasOwnProperty('user') && req.user.hasOwnProperty('uid') && parseInt(req.user.uid, 10) > 10;

};
// 로그아웃 함수.
plugin.doLogout = function (data, callback)	{
	winston.info('Do logout..');

	if (typeof callback === 'function')	{
		callback();
	} else {
		return true;
	}
}

module.exports = plugin;<commit_msg>20170405141341<commit_after>'use strict';

var meta = module.parent.require('./meta');
var user = module.parent.require('./user');
var nconf = require('nconf');

var db = module.parent.require('./database'); // NodeBB / src / database 참고.
var au = module.parent.require('./controllers/authentication'); // NodeBB / src / controllers 참고.

var winston = require('winston');

var mongocli = require('mongodb').MongoClient;
var biourl = 'mongodb://localhost:27017/biobank-session';

// 모듈 객체.
var plugin = {};

plugin.init = function (params, callback)	{
	var router = params.router;

	winston.info('Start community..');

	router.get('/community', function ()	{
		console.log(arguments);
	});

	callback();
}

plugin.verifyUser = function (token, callback)	{

}

// 이 함수는 NodeBB 에서 어떤 동작 또는 페이지이동 때마다 호출되므로 계속해서 토큰을 받아오고 유저 유효성 검사를 할 것이다.
// 그러므로 함수 첫줄에 세션 확인을 하는 구문을 만들어 같은 세션일 경우 유저 유효성 검사를 넘어가도록 한다.
plugin.addMiddleware = function (req, res, next)	{
	nconf.set('mongo:database', 'biobank-session');
	var newdb = nconf.get('mongo:database');

	mongocli.connect(url, function (err, db)	{
		console.log('connected');

		db.close();
	})

	console.log('login add middle ware!!', req.headers.cookie);
	// 이미 있는 세션일 경우 요청 프로퍼티에 user 와 user 안에 uid 가 존재 한다.
	// TODO.
	// 로그아웃 후 창을 닫고 바이오클라우드에서 다시 커뮤니티로 접속하면 세션관련 리프레쉬가 발생한다.
	// 이 경우 세션이 변경됨을 확인하고 리프레쉬를 해줘야한다.
	var hasSession = req.hasOwnProperty('user') && req.user.hasOwnProperty('uid') && parseInt(req.user.uid, 10) > 10;

};
// 로그아웃 함수.
plugin.doLogout = function (data, callback)	{
	winston.info('Do logout..');

	if (typeof callback === 'function')	{
		callback();
	} else {
		return true;
	}
}

module.exports = plugin;<|endoftext|>


<commit_before>String.prototype.capitalize = function() {
	for(var i = 0, arr = this.split(' '); i < arr.length; i++) {
		var str = arr[i];
		if(str != "of") arr[i] = str.charAt(0).toUpperCase() + str.substr(1);
	}
	return arr.join(' ');
}; // capitalize all words, separated by spaces, excluding "of": str.capitalize();
function R(a) {
	return a[Math.floor(Math.random() * a.length)];
} // select random element from array or string
function r(n) {
	return n ? Math.random() <= n : Math.random();
} // return random decimal, optionally compares it with parameter.
function log(str) {
	if(debug) info.innerHTML += ++debugStep + ': ' + str + '
';
}
var timer,
	consonants = 'bcdfghjklmnpqrstvwxyz',
	vowels = 'aeiouy',
	consonants_start_2 = ['kn', 'pn', 'wr', 'ts', 'tw'],
	consonants_start_$h = ['g', 'p', 't', 'c', 's', 'sc', 'sp', 'k', 'w'], // Khaaaaaaan!!!
	consonants_start_$l = ['b', 'c', 'f', 'g', 'k', 'p', 'ph', 'ch', 'sp'], // $ is a placeholder
	consonants_start_$r = ['b', 'c', 'f', 'g', 'k', 'p', 't', 'ph', 'th', 'ch', 'sh', 'st', 'sc', 'sp'],
	consonants_start_s$ = 'cklmnpqtvw', // tr is not added. (st is present in $r for "str")
	// vowel_2, // use function instead, simpler.
	vowel_3 = ['eau'], // That's it?
	vowel_$r = ['a', 'e', 'i', 'o', 'u', 'y', 'ae', 'ai', 'au', 'ea', 'ee', 'ei', 'eu', 'ia', 'ie', 'io', 'oa', 'oe', 'oi', 'oo', 'ou', 'ua', 'ue'],
	vowel_$l = ['a', 'e', 'i', 'o', 'u', 'y', 'ai', 'au', 'ea', 'ee', 'ei', 'ia', 'ie', 'io', 'oa', 'oe', 'oi', 'oo', 'ou', 'ua', 'ue', 'ui'],
	vowel_$rl = 'aeiou',
	vowel_$w = 'aeo',
	vowel_$n = ['a', 'e', 'i', 'o', 'u', 'y', 'ai', 'au', 'ea', 'ee', 'ei', 'ia', 'ie', 'io', 'oa', 'oo', 'ua', 'ui'],
	vowel_$ng = vowel_$rl, // same
	vowel_$gh = ['ai', 'ou', 'ei', 'au'],
	consonants_end = 'bcdfghkmnpstvxz',
	consonants_end_2 = ['mb', 'mp', 'ck', 'cq', 'dg', 'ts'],
	consonants_end_$h = ['c', 's', 'p', 't', 'tc'],
	consonants_end_$t = 'cfkpsx',
	consonants_end_s$ = 'kmpt',
	consonants_end_double = ['bb', 'cc', 'dd', 'ff', 'gg', 'll', 'nn', 'pp', 'rr', 'ss', 'tt', 'zz'],
	presets = ['tion', 'sion', 'cion', 'xion'],
	directions = ['north', 'south', 'east', 'west', 'central', ''],
	country_prefix = ['new', 'united', 'united states of', 'republic of', 'empire of', 'imperial', 'great', 'greater', ''],
	country_suffix = ['a', 'ia', 'stan', 'land', 'ar', 'es', 'rus', 'na', 'ua', 'ea', ''],
	country_suffix_word = ['federation', 'kingdom', 'states', 'republic', 'empire', 'union', ''],
	city_prefix = ['new ', 'st. ', 'los ', 'novo', ''],
	city_suffix = ['grad', 'gorod', 'sk', 'ton', 'ville', 'berg', 'burg', 'jing', 'polis', 'by', 'ad', ' city', ''],
	punctuation = ['.', ',', '!', '?', ':', ';', '...'],
	punctuation_end = '.,!?',
	paragraph_end = ['.', '!', '?', '...'],
	debug = true, // log all actions
	debugStep = 0; // for logging

function vowel_2() {
	var str = R(vowels) + R(vowels);
	if(str.match(/[iy]{2}/)) return str.charAt(0); // if string is ii, iy, yi, or yy.
	return str;
}

function globalReplace(word, option) {
	log(word);
	if(option && r(.9)) { // prefixing and suffixing (country/city specific)
		if(option == 1) {
			if(r(.4)) word += R(country_suffix);
			var rand = r();
			if(rand < .3) word = R(directions) + ' ' + word;
			else if(rand < .6) word = R(country_prefix) + ' ' + word;
			else if(rand < .9) word += ' ' + R(country_suffix_word);
		} else {
			if(r(.5)) word += R(city_suffix);
			else if(r(.8)) word = R(city_prefix) + word; // prefix word should be rarer.
		}
		log(word + ((option == 1) ? " (countrified)" : " (citified)"));
	}
	word = word.replace(/[bcdfghjklmnpqrstvwxz]{5,}/g, function(match) { return match.substr(0, 4); }) // replace 5 consonants with 4
		.replace(/[aeiouy]{4,}/g, function(match) { return match.substr(1, 3); }) // replace 4 vowels with 3
		.replace(/((.)\2\2\2|(.)\3\3)/g, function(match) { return match.substr(0, 2); }) // replace 3 or 4 repeating letters
		.replace(/[bcdfghjklmnpqrstvwxz]([bcdfglnprstz])\1/g, function(match) { return match.substr(0, 2); }) // replace awkward double consonants
		.replace(/[iy]{2,}/g, function(match) { return match.charAt(0); }) // replace ii, iy, yi, yy
		.replace(/^x[^eyia]/g, function(match) { return match.substr(1); }) // replace [start of string]+x+[?] with [*]
		.replace(/[^ srlhvaeiouy]v/g, function(match) { return match.charAt(0); }) // replace [not:srlhvaeiouy]+v with [*]
		.replace(/.?k.k/g, function(match) { return match.slice(-2); }) // Don't let things like "cksk" slip (via citify)
		.replace(/dg$/, 'dge') // dg ending add e
		.replace(/q([^u])/g, 'qu$1'); // add u after q
	log(word + " (adjusted)");
	return word;
}

function localReplace(syl) {
	syl = syl.replace(/nm/g, function() { return r(.5) ? 'n' : 'm' }); // no m following n, pick one.
	syl = syl.replace(/gh[bcdfghkmpvxz]/g, function(match) { return match.substr(2); }); // gh non-silent
	return syl;
}
// MAIN WORD GENERATOR
// Uses: var foo = word(3,"country"); var bar = word(2); var baz = word(4,2); var qux = word(1,false);
function word(syllables, option) { // accepted options: 1, 2, "country", "city", [falsy value]
	if(option == "country") option = 1;
	else if(option == "city") option = 2;
	if(syllables == 2 && r(0.0025)) return 'ayylmao'; // remove if not suitable
	var str = '',
		state = {
			start: true,
			end: false,
			consonantStart: false,
			consonantEnd: false,
			isLong: false
		},
		syl = '';
	for(var i = 0; i < syllables; i++) {
		if(r(.03) && !state.start && !option) syl = R(presets);
		else syl = localReplace(syllable(state));
		log(syl);
		state = updateState(syl);
		state.end = (i + 1) === syllables;
		str += syl;
	}
	return globalReplace(str, option);
}

function updateState(syllable) {
	var state = {
		start: false,
		end: false,
		consonantStart: false,
		consonantEnd: false,
		isLong: false
	};
	if(syllable.length >= 4) state.isLong = true;
	if(/^[bcdfghjklmnpqrstvwxyz]/.test(syllable)) state.consonantStart = true;
	if(/[bcdfghjklmnpqrstvwxyz]$/.test(syllable)) state.consonantEnd = true;
	return state;
}

function syllable(state) {
	var syl = '',
		rand = r(),
		shorten = false;
	if(state.start) {
		if(r(.5 + state.consonantEnd / 10)) syl += R(consonants);
		else if(r(.2 + state.consonantStart / 10 + state.consonantEnd / 10)) {
			if(rand < .2) syl += R(consonants_start_$h) + 'h';
			else if(rand < .4) syl += R(consonants_start_$l) + 'l';
			else if(rand < .6) syl += R(consonants_start_$r) + 'r';
			else if(rand < .8) syl += 's' + R(consonants_start_s$);
			else syl += R(consonants_start_2);
		}
	}
	rand = r();
	if(r(.9 + state.isLong / 10)) {
		if(rand < .01) syl += R(vowel_3);
		else if(rand < .5) syl += R(vowels);
		else if(rand < .6) syl += vowel_2(); // function
		else if(rand < .7) syl += R(vowel_$r) + 'r';
		else if(rand < .8) syl += R(vowel_$l) + 'l';
		else if(rand < .9) syl += R(vowel_$n) + 'n';
		else syl += R(vowel_$w) + 'w';
	} else {
		if(rand < .33) syl += R(vowel_$gh) + 'gh';
		else if(rand < .66) syl += R(vowel_$rl) + 'rl';
		else if(rand < .99) syl += R(vowel_$ng) + 'ng';
		else syl += R(vowel_3);
		shorten = true;
	}
	rand = r();
	if(shorten) syl += r(.8) ? R(consonants_end) : '';
	else if(r(.8 + state.consonantStart / 10)) {
		if(rand < .5) syl += R(consonants_end);
		else if(rand < .6) syl += R(consonants_end_2);
		else if(rand < .7) syl += R(consonants_end_$h) + 'h';
		else if(rand < .8) syl += R(consonants_end_$t) + 't';
		else if(rand < .9) syl += 's' + R(consonants_end_s$);
		else syl += R(consonants_end_double);
	}
	if(state.end && r(.1)) syl += 'e';
	return syl;
}

function display() {
	debugStep=0;
	info.innerHTML='';
	result.innerHTML=word(Math.min(+iteration.value,10),+type.value).capitalize();
	return false;
}

function paragraph() {
	var temp = debug;
	debug = false;
	timer = setInterval(sentence, 5);
	setTimeout(function() {
		clearInterval(timer);
		par.value = par.value.replace(/[,;:] $/, R(paragraph_end) + ' ')
			.replace(/ $/, '\r');
		debug = temp;
		par.scrollTop = par.scrollHeight;
	}, 20 + r() * 20); // crappy timing loop control
}

function sentence() {
	var sen = word(r() * 3 + 1 | 0)
		.capitalize();
	for(var i = 0; i < r() * 10 + 3; i++) sen += ' ' + word(r() * 3.95 + 1.15 | 0);
	if(r(0.05)) {
		sen = '"' + sen + R(punctuation_end) + '" ';
		par.value += sen;
		return;
	}
	if(r(0.7)) sen += '. ';
	else if(r(0.4)) {
		sen += r(0.5) ? '! ' : '? ';
	} else sen += R(punctuation) + ' ';
	par.value += sen;
}
<commit_msg>Add globalReplace rule<commit_after>String.prototype.capitalize = function() {
	for(var i = 0, arr = this.split(' '); i < arr.length; i++) {
		var str = arr[i];
		if(str != "of") arr[i] = str.charAt(0).toUpperCase() + str.substr(1);
	}
	return arr.join(' ');
}; // capitalize all words, separated by spaces, excluding "of": str.capitalize();
function R(a) {
	return a[Math.floor(Math.random() * a.length)];
} // select random element from array or string
function r(n) {
	return n ? Math.random() <= n : Math.random();
} // return random decimal, optionally compares it with parameter.
function log(str) {
	if(debug) info.innerHTML += ++debugStep + ': ' + str + '
';
}
var timer,
	consonants = 'bcdfghjklmnpqrstvwxyz',
	vowels = 'aeiouy',
	consonants_start_2 = ['kn', 'pn', 'wr', 'ts', 'tw'],
	consonants_start_$h = ['g', 'p', 't', 'c', 's', 'sc', 'sp', 'k', 'w'], // Khaaaaaaan!!!
	consonants_start_$l = ['b', 'c', 'f', 'g', 'k', 'p', 'ph', 'ch', 'sp'], // $ is a placeholder
	consonants_start_$r = ['b', 'c', 'f', 'g', 'k', 'p', 't', 'ph', 'th', 'ch', 'sh', 'st', 'sc', 'sp'],
	consonants_start_s$ = 'cklmnpqtvw', // tr is not added. (st is present in $r for "str")
	// vowel_2, // use function instead, simpler.
	vowel_3 = ['eau'], // That's it?
	vowel_$r = ['a', 'e', 'i', 'o', 'u', 'y', 'ae', 'ai', 'au', 'ea', 'ee', 'ei', 'eu', 'ia', 'ie', 'io', 'oa', 'oe', 'oi', 'oo', 'ou', 'ua', 'ue'],
	vowel_$l = ['a', 'e', 'i', 'o', 'u', 'y', 'ai', 'au', 'ea', 'ee', 'ei', 'ia', 'ie', 'io', 'oa', 'oe', 'oi', 'oo', 'ou', 'ua', 'ue', 'ui'],
	vowel_$rl = 'aeiou',
	vowel_$w = 'aeo',
	vowel_$n = ['a', 'e', 'i', 'o', 'u', 'y', 'ai', 'au', 'ea', 'ee', 'ei', 'ia', 'ie', 'io', 'oa', 'oo', 'ua', 'ui'],
	vowel_$ng = vowel_$rl, // same
	vowel_$gh = ['ai', 'ou', 'ei', 'au'],
	consonants_end = 'bcdfghkmnpstvxz',
	consonants_end_2 = ['mb', 'mp', 'ck', 'cq', 'dg', 'ts'],
	consonants_end_$h = ['c', 's', 'p', 't', 'tc'],
	consonants_end_$t = 'cfkpsx',
	consonants_end_s$ = 'kmpt',
	consonants_end_double = ['bb', 'cc', 'dd', 'ff', 'gg', 'll', 'nn', 'pp', 'rr', 'ss', 'tt', 'zz'],
	presets = ['tion', 'sion', 'cion', 'xion'],
	directions = ['north', 'south', 'east', 'west', 'central', ''],
	country_prefix = ['new', 'united', 'united states of', 'republic of', 'empire of', 'imperial', 'great', 'greater', ''],
	country_suffix = ['a', 'ia', 'stan', 'land', 'ar', 'es', 'rus', 'na', 'ua', 'ea', ''],
	country_suffix_word = ['federation', 'kingdom', 'states', 'republic', 'empire', 'union', ''],
	city_prefix = ['new ', 'st. ', 'los ', 'novo', ''],
	city_suffix = ['grad', 'gorod', 'sk', 'ton', 'ville', 'berg', 'burg', 'jing', 'polis', 'by', 'ad', ' city', ''],
	punctuation = ['.', ',', '!', '?', ':', ';', '...'],
	punctuation_end = '.,!?',
	paragraph_end = ['.', '!', '?', '...'],
	debug = true, // log all actions
	debugStep = 0; // for logging

function vowel_2() {
	var str = R(vowels) + R(vowels);
	if(str.match(/[iy]{2}/)) return str.charAt(0); // if string is ii, iy, yi, or yy.
	return str;
}

function globalReplace(word, option) {
	log(word);
	if(option && r(.9)) { // prefixing and suffixing (country/city specific)
		if(option == 1) {
			if(r(.4)) word += R(country_suffix);
			var rand = r();
			if(rand < .3) word = R(directions) + ' ' + word;
			else if(rand < .6) word = R(country_prefix) + ' ' + word;
			else if(rand < .9) word += ' ' + R(country_suffix_word);
		} else {
			if(r(.5)) word += R(city_suffix);
			else if(r(.8)) word = R(city_prefix) + word; // prefix word should be rarer.
		}
		log(word + ((option == 1) ? " (countrified)" : " (citified)"));
	}
	word = word.replace(/[bcdfghjklmnpqrstvwxz]{5,}/g, function(match) { return match.substr(0, 4); }) // replace 5 consonants with 4
		.replace(/[aeiouy]{4,}/g, function(match) { return match.substr(1, 3); }) // replace 4 vowels with 3
		.replace(/((.)\2\2\2|(.)\3\3)/g, function(match) { return match.substr(0, 2); }) // replace 3 or 4 repeating letters
		.replace(/[bcdfghjklmnpqrstvwxz]([bcdfglnprstz])\1/g, function(match) { return match.substr(0, 2); }) // replace awkward double consonants
		.replace(/[iy]{2,}/g, function(match) { return match.charAt(0); }) // replace ii, iy, yi, yy
		.replace(/^x[^eyia]/g, function(match) { return match.substr(1); }) // replace [start of string]+x+[?] with [*]
		.replace(/[^aieu]xion/g, function(match) { return R("aieu") + 'xion'; }) // add vowel before xion
		.replace(/[^ srlhvaeiouy]v/g, function(match) { return match.charAt(0); }) // replace [not:srlhvaeiouy]+v with [*]
		.replace(/.?k.k/g, function(match) { return match.slice(-2); }) // Don't let things like "cksk" slip (via citify)
		.replace(/dg$/, 'dge') // dg ending add e
		.replace(/q([^u])/g, 'qu$1'); // add u after q
	log(word + " (adjusted)");
	return word;
}

function localReplace(syl) {
	syl = syl.replace(/nm/g, function() { return r(.5) ? 'n' : 'm' }); // no m following n, pick one.
	syl = syl.replace(/gh[bcdfghkmpvxz]/g, function(match) { return match.substr(2); }); // gh non-silent
	return syl;
}
// MAIN WORD GENERATOR
// Uses: var foo = word(3,"country"); var bar = word(2); var baz = word(4,2); var qux = word(1,false);
function word(syllables, option) { // accepted options: 1, 2, "country", "city", [falsy value]
	if(option == "country") option = 1;
	else if(option == "city") option = 2;
	if(syllables == 2 && r(0.0025)) return 'ayylmao'; // remove if not suitable
	var str = '',
		state = {
			start: true,
			end: false,
			consonantStart: false,
			consonantEnd: false,
			isLong: false
		},
		syl = '';
	for(var i = 0; i < syllables; i++) {
		if(r(.03) && !state.start && !option) syl = R(presets);
		else syl = localReplace(syllable(state));
		log(syl);
		state = updateState(syl);
		state.end = (i + 1) === syllables;
		str += syl;
	}
	return globalReplace(str, option);
}

function updateState(syllable) {
	var state = {
		start: false,
		end: false,
		consonantStart: false,
		consonantEnd: false,
		isLong: false
	};
	if(syllable.length >= 4) state.isLong = true;
	if(/^[bcdfghjklmnpqrstvwxyz]/.test(syllable)) state.consonantStart = true;
	if(/[bcdfghjklmnpqrstvwxyz]$/.test(syllable)) state.consonantEnd = true;
	return state;
}

function syllable(state) {
	var syl = '',
		rand = r(),
		shorten = false;
	if(state.start) {
		if(r(.5 + state.consonantEnd / 10)) syl += R(consonants);
		else if(r(.2 + state.consonantStart / 10 + state.consonantEnd / 10)) {
			if(rand < .2) syl += R(consonants_start_$h) + 'h';
			else if(rand < .4) syl += R(consonants_start_$l) + 'l';
			else if(rand < .6) syl += R(consonants_start_$r) + 'r';
			else if(rand < .8) syl += 's' + R(consonants_start_s$);
			else syl += R(consonants_start_2);
		}
	}
	rand = r();
	if(r(.9 + state.isLong / 10)) {
		if(rand < .01) syl += R(vowel_3);
		else if(rand < .5) syl += R(vowels);
		else if(rand < .6) syl += vowel_2(); // function
		else if(rand < .7) syl += R(vowel_$r) + 'r';
		else if(rand < .8) syl += R(vowel_$l) + 'l';
		else if(rand < .9) syl += R(vowel_$n) + 'n';
		else syl += R(vowel_$w) + 'w';
	} else {
		if(rand < .33) syl += R(vowel_$gh) + 'gh';
		else if(rand < .66) syl += R(vowel_$rl) + 'rl';
		else if(rand < .99) syl += R(vowel_$ng) + 'ng';
		else syl += R(vowel_3);
		shorten = true;
	}
	rand = r();
	if(shorten) syl += r(.8) ? R(consonants_end) : '';
	else if(r(.8 + state.consonantStart / 10)) {
		if(rand < .5) syl += R(consonants_end);
		else if(rand < .6) syl += R(consonants_end_2);
		else if(rand < .7) syl += R(consonants_end_$h) + 'h';
		else if(rand < .8) syl += R(consonants_end_$t) + 't';
		else if(rand < .9) syl += 's' + R(consonants_end_s$);
		else syl += R(consonants_end_double);
	}
	if(state.end && r(.1)) syl += 'e';
	return syl;
}

function display() {
	debugStep=0;
	info.innerHTML='';
	result.innerHTML=word(Math.min(+iteration.value,10),+type.value).capitalize();
	return false;
}

function paragraph() {
	var temp = debug;
	debug = false;
	timer = setInterval(sentence, 5);
	setTimeout(function() {
		clearInterval(timer);
		par.value = par.value.replace(/[,;:] $/, R(paragraph_end) + ' ')
			.replace(/ $/, '\r');
		debug = temp;
		par.scrollTop = par.scrollHeight;
	}, 20 + r() * 20); // crappy timing loop control
}

function sentence() {
	var sen = word(r() * 3 + 1 | 0)
		.capitalize();
	for(var i = 0; i < r() * 10 + 3; i++) sen += ' ' + word(r() * 3.95 + 1.15 | 0);
	if(r(0.05)) {
		sen = '"' + sen + R(punctuation_end) + '" ';
		par.value += sen;
		return;
	}
	if(r(0.7)) sen += '. ';
	else if(r(0.4)) {
		sen += r(0.5) ? '! ' : '? ';
	} else sen += R(punctuation) + ' ';
	par.value += sen;
}
<|endoftext|>


<commit_before>"use strict";

var plugin = {},
	winston = module.parent.require('winston'),
	async = module.parent.require('async'),
	user = module.parent.require('./user'),
	superusers;

plugin.init = function(app, middleware, controllers, callback) {
	try {
		superusers = require('../nodebb-plugin-superusers/library');
	} catch (e) {
		winston.warn('Please install and activate the SuperUsers plugin in order for this to work.');
		return callback();
	}

	var SocketPlugins = module.parent.require('./socket.io/plugins');
		SocketPlugins.superuser = SocketPlugins.superuser || {};
		SocketPlugins.superuser.squash = squash;
		SocketPlugins.superuser.unsquash = unsquash;

	callback();
};

plugin.getUsersPosts = function(data, callback) {
	var userCache = {},
		posts = [];

	async.eachSeries(data.posts, function(post, next) {
		var postUid = parseInt(post.uid, 10);

		if (postUid === parseInt(data.uid, 10)) {
			posts.push(post);
			return next();
		} else if (userCache[postUid]) {
			post.deleted = userCache[postUid];
			posts.push(post);
			return next();
		} else {
			user.getUserField(postUid, 'squashed', function(err, squashed) {
				post.deleted = squashed;
				posts.push(post);
				userCache[postUid] = squashed;

				return next();
			});
		}
	}, function(err) {
		data.posts = posts;
		callback(err, data);
	});
};

function squash(socket, data, callback) {
	var uid = socket.uid ? socket.uid : 0;
	superusers.isSuperUser(uid, function(err, isSuperUser) {
		if (!isSuperUser) {
			return callback(new Error('Not Allowed'));
		}

		user.setUserField(data.uid, 'squashed', 1, callback);
	});
}

function unsquash(socket, data, callback) {
	var uid = socket.uid ? socket.uid : 0;
	superusers.isSuperUser(uid, function(err, isSuperUser) {
		if (!isSuperUser) {
			return callback(new Error('Not Allowed'));
		}

		user.setUserField(data.uid, 'squashed', 0, callback);
	});
}

module.exports = plugin;<commit_msg>squash functionality actually complete!<commit_after>"use strict";

var plugin = {},
	winston = module.parent.require('winston'),
	async = module.parent.require('async'),
	user = module.parent.require('./user'),
	superusers;

plugin.init = function(app, middleware, controllers, callback) {
	try {
		superusers = require('../nodebb-plugin-superusers/library');
	} catch (e) {
		winston.warn('Please install and activate the SuperUsers plugin in order for this to work.');
		return callback();
	}

	var SocketPlugins = module.parent.require('./socket.io/plugins');
		SocketPlugins.superuser = SocketPlugins.superuser || {};
		SocketPlugins.superuser.squash = squash;
		SocketPlugins.superuser.unsquash = unsquash;

	callback();
};

plugin.getUsersPosts = function(data, callback) {
	var userCache = {},
		posts = [];

	async.eachSeries(data.posts, function(post, next) {
		var postUid = parseInt(post.uid, 10);

		if (postUid === parseInt(data.uid, 10) || parseInt(post.deleted, 10) === 1) {
			posts.push(post);
			return next();
		} else if (typeof userCache[postUid] !== 'undefined') {
			if (userCache[postUid] === 0) {
				posts.push(post);
			}

			return next();
		} else {
			user.getUserField(postUid, 'squashed', function(err, squashed) {
				squashed = squashed ? parseInt(squashed, 10) : 0;

				if (squashed === 0) {
					posts.push(post);
				}

				userCache[postUid] = squashed;
				return next();
			});
		}
	}, function(err) {
		data.posts = posts;
		callback(err, data);
	});
};

function squash(socket, data, callback) {
	var uid = socket.uid ? socket.uid : 0;
	superusers.isSuperUser(uid, function(err, isSuperUser) {
		if (!isSuperUser) {
			return callback(new Error('Not Allowed'));
		}

		user.setUserField(data.uid, 'squashed', 1, callback);
	});
}

function unsquash(socket, data, callback) {
	var uid = socket.uid ? socket.uid : 0;
	superusers.isSuperUser(uid, function(err, isSuperUser) {
		if (!isSuperUser) {
			return callback(new Error('Not Allowed'));
		}

		user.setUserField(data.uid, 'squashed', 0, callback);
	});
}

module.exports = plugin;<|endoftext|>


<commit_before>(function() {
    "use strict";
    /* jshint indent: 4 */
    var	request = require('request'),
        async = module.parent.require('async'),
        winston = module.parent.require('winston'),
        S = module.parent.require('string'),
        meta = module.parent.require('./meta'),
        gifconvertRegex = /\.(gif)\b/g,
        Embed = {},
        cache, appModule;
    var getgifconvert = function(gifconvertKey, callback) {
        var gifconvertNum = gifconvertKey;
        request.get({
            url: 'http://upload.gifconvert.com/transcode?fetchUrl=' + gifconvertNum + '.gif'
        }, function (err, response, body) {
            if (!err && response.statusCode === 200) {
                var gifconvertData = JSON.parse(body);
                if (!gifconvertData) {
                    return callback(null, {});
                }
                winston.warn(err, response, gifconvertKey)
                callback(null, {
                    width: gifconvertData.width,
                    height: gifconvertData.height,
                    webmUrl: gifconvertData.webmUrl,
                    gifUrl: gifconvertData.gifUrl,
                    mp4Url: gifconvertData.mp4Url,
                    gfyId: gifconvertData.gfyId,
                    numFrames: gifconvertData.numFrames
                });
            } else {
                callback(err);
            }
        });
    };
    Embed.init = function(app, middleware, controllers, callback) {
        function render(req, res, next) {
            res.render('partials/gifconvert-block', {});
        }
        appModule = app;
        if ( callback )
        callback();
    };
    Embed.parse = function(raw, callback) {
        var gifconvertKeys = [],
            matches, cleanedText;
        cleanedText = S(raw).stripTags().s;
        matches = cleanedText.match(gifconvertRegex);
        if (matches && matches.length) {
            matches.forEach(function(match) {
                if (gifconvertKeys.indexOf(match) === -1) {
                    gifconvertKeys.push(match);
                }
            });
        }
        async.map(gifconvertKeys, function(gifconvertKey, next) {
            if (cache.has(gifconvertKey)) {
                next(null, cache.get(gifconvertKey));
            } else {
                getgifconvert(gifconvertKey, function(err, gifconvertObj) {
                    if (err) {
                        return next(err);
                    }
                    cache.set(gifconvertKey, gifconvertObj);
                    next(err, gifconvertObj);
                });
            }
        }, function(err, gifconvertinfo) {
            if (!err) {
// Filter
                gifconvertinfo = gifconvertinfo.filter(function(issue) {
                    return issue;
                });
                appModule.render('partials/gifconvert-block', {
                    gifconvertinfo: gifconvertinfo
                }, function(err, html) {
                    callback(null, raw += html);
                });
            } else {
                winston.warn('Couldn\'t Filter', gifconvertinfo);
                callback(null, raw);
            }
        });
    };
// Initial setup
    cache = require('lru-cache')({
        maxAge: 1000*60*60*24,
        max: 100
    });
    module.exports = Embed;
})();<commit_msg>URL change<commit_after>(function() {
    "use strict";
    /* jshint indent: 4 */
    var	request = require('request'),
        async = module.parent.require('async'),
        winston = module.parent.require('winston'),
        S = module.parent.require('string'),
        meta = module.parent.require('./meta'),
        gifconvertRegex = /\.(gif)\b/g,
        Embed = {},
        cache, appModule;
    var getgifconvert = function(gifconvertKey, callback) {
        var gifconvertNum = gifconvertKey;
        request.get({
            url: 'http://upload.gfycat.com/transcode?fetchUrl=' + gifconvertNum + '.gif'
        }, function (err, response, body) {
            if (!err && response.statusCode === 200) {
                var gifconvertData = JSON.parse(body);
                if (!gifconvertData) {
                    return callback(null, {});
                }
                winston.warn(err, response, gifconvertKey)
                callback(null, {
                    width: gifconvertData.width,
                    height: gifconvertData.height,
                    webmUrl: gifconvertData.webmUrl,
                    gifUrl: gifconvertData.gifUrl,
                    mp4Url: gifconvertData.mp4Url,
                    gfyId: gifconvertData.gfyId,
                    numFrames: gifconvertData.numFrames
                });
            } else {
                callback(err);
            }
        });
    };
    Embed.init = function(app, middleware, controllers, callback) {
        function render(req, res, next) {
            res.render('partials/gifconvert-block', {});
        }
        appModule = app;
        if ( callback )
        callback();
    };
    Embed.parse = function(raw, callback) {
        var gifconvertKeys = [],
            matches, cleanedText;
        cleanedText = S(raw).stripTags().s;
        matches = cleanedText.match(gifconvertRegex);
        if (matches && matches.length) {
            matches.forEach(function(match) {
                if (gifconvertKeys.indexOf(match) === -1) {
                    gifconvertKeys.push(match);
                }
            });
        }
        async.map(gifconvertKeys, function(gifconvertKey, next) {
            if (cache.has(gifconvertKey)) {
                next(null, cache.get(gifconvertKey));
            } else {
                getgifconvert(gifconvertKey, function(err, gifconvertObj) {
                    if (err) {
                        return next(err);
                    }
                    cache.set(gifconvertKey, gifconvertObj);
                    next(err, gifconvertObj);
                });
            }
        }, function(err, gifconvertinfo) {
            if (!err) {
// Filter
                gifconvertinfo = gifconvertinfo.filter(function(issue) {
                    return issue;
                });
                appModule.render('partials/gifconvert-block', {
                    gifconvertinfo: gifconvertinfo
                }, function(err, html) {
                    callback(null, raw += html);
                });
            } else {
                winston.warn('Couldn\'t Filter', gifconvertinfo);
                callback(null, raw);
            }
        });
    };
// Initial setup
    cache = require('lru-cache')({
        maxAge: 1000*60*60*24,
        max: 100
    });
    module.exports = Embed;
})();<|endoftext|>


<commit_before>const WS = require("ws");
const wss = new WS.Server({ noServer: true });
const url = require('url');
const crypto = require("crypto");
const security = require("./security");
let client_count = 0;

const md5 = s => {
    return crypto.createHash('md5').update(String(s)).digest("hex");
}

wss.on('connection', function connection(ws, req) {
    // console.log(req);
    try {
        let client_id_string = `client-${client_count++}-${+new Date()}`;
        let client_id = md5(client_id_string);
        let msg_count = 0;
        ws.on('message', function message(msg) {
            try {
                let msg_id_string = `msg-${msg_count++}-${+new Date()}`;
                let msg_id = md5(msg_id_string);
                console.log(`Received message from ${client_id_string} (${msg_id_string})`);
                handleMessage(msg, client_id, msg_id);
            } catch(err) {
                console.error("message error", err);
            }
        });
    } catch(err) {
        console.error("connection error", err);
    }
});

const upgrade = async (req, socket, head) => {
    try {
        const pathname = url.parse(req.url).pathname;
        if (pathname !== "/websocket") throw("Only /websocket endpoint supported");
        wss.handleUpgrade(req, socket, head, function done(ws) {
            wss.emit('connection', ws, req);
        });
    } catch(err) {
        console.log("Websocket Auth failed");
        socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
        socket.destroy();
    }
}

const handleMessage = (msg, client_id, msg_id)=> {
    // console.log(`Received message ${msg} from ${client_id} (${msg_id})`);
    try {
        if (typeof msg !== "object") throw "msg should be an object";
    } catch(err) {
        console.error(err);
    }
}

module.exports = {
    upgrade
};<commit_msg>Some notes<commit_after>/*
$auth
$subscribe
$fetch
*/

const WS = require("ws");
const wss = new WS.Server({ noServer: true });
const url = require('url');
const crypto = require("crypto");
const security = require("./security");
let client_count = 0;

const md5 = s => {
    return crypto.createHash('md5').update(String(s)).digest("hex");
}

wss.on('connection', function connection(ws, req) {
    // console.log(req);
    try {
        let client_id_string = `client-${client_count++}-${+new Date()}`;
        let client_id = md5(client_id_string);
        let msg_count = 0;
        ws.on('message', function message(msg) {
            try {
                let msg_id_string = `msg-${msg_count++}-${+new Date()}`;
                let msg_id = md5(msg_id_string);
                console.log(`Received message from ${client_id_string} (${msg_id_string})`);
                handleMessage(msg, client_id, msg_id);
            } catch(err) {
                console.error("message error", err);
            }
        });
    } catch(err) {
        console.error("connection error", err);
    }
});

const upgrade = async (req, socket, head) => {
    try {
        const pathname = url.parse(req.url).pathname;
        if (pathname !== "/websocket") throw("Only /websocket endpoint supported");
        wss.handleUpgrade(req, socket, head, function done(ws) {
            wss.emit('connection', ws, req);
        });
    } catch(err) {
        console.log("Websocket Auth failed");
        socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
        socket.destroy();
    }
}

const handleMessage = (msg, client_id, msg_id)=> {
    // console.log(`Received message ${msg} from ${client_id} (${msg_id})`);
    try {
        if (typeof msg !== "object") throw "msg should be an object";

    } catch(err) {
        console.error(err);
    }
}

module.exports = {
    upgrade
};<|endoftext|>


<commit_before>(function(window) {

  var haveLocalStorage;
  var LS_STATE_KEY = "remotestorage:widget:state";
  function stateSetter(widget, state) {
    return function() {
      if(haveLocalStorage) {
        localStorage[LS_STATE_KEY] = state;
      }
      if(widget.view) {
        if(widget.rs.remote) {
          widget.view.setUserAddress(widget.rs.remote.userAddress);
        }
        widget.view.setState(state, arguments);
      }
    };
  }
  function errorsHandler(widget){
    //decided to not store error state
    return function(error){
      if(error instanceof RemoteStorage.DiscoveryError) {
        console.log('discovery failed',  error, '"' + error.message + '"');
        widget.view.setState('initial', [error.message]);
      } else if(error instanceof RemoteStorage.SyncError) {
        widget.view.setState('offline', []);
      } else {
        widget.view.setState('error', [error]);
      }
    }
  }
  RemoteStorage.Widget = function(remoteStorage) {
    this.rs = remoteStorage;
    this.rs.on('ready', stateSetter(this, 'connected'));
    this.rs.on('disconnected', stateSetter(this, 'initial'));
    //this.rs.on('connecting', stateSetter(this, 'connecting'))
    this.rs.on('authing', stateSetter(this, 'authing'));
    this.rs.on('sync-busy', stateSetter(this, 'busy'));
    this.rs.on('sync-done', stateSetter(this, 'connected'));
    this.rs.on('error', errorsHandler(this) );
    if(haveLocalStorage) {
      var state = localStorage[LS_STATE_KEY] = state;
      if(state) {
        this._rememberedState = state;
      }
    }
  };

  RemoteStorage.Widget.prototype = {
    display: function() {
      if(! this.view) {
        this.setView(new View());
      }
      this.view.display.apply(this.view, arguments);
      return this;
    },

    setView: function(view) {
      this.view = view;
      this.view.on('connect', this.rs.connect.bind(this.rs));
      this.view.on('disconnect', this.rs.disconnect.bind(this.rs));
      this.view.on('sync', this.rs.sync.bind(this.rs));
      this.view.on('reset', function(){
        this.rs.on('disconnected', document.location.reload.bind(document.location))
        this.rs.disconnect()
      }.bind(this));

      if(this._rememberedState) {
        stateSetter(this, this._rememberedState)();
        delete this._rememberedState;
      }
    }
  };

  RemoteStorage.prototype.displayWidget = function() {
    this.widget.display();
  };

  RemoteStorage.Widget._rs_init = function(remoteStorage) {
    if(! remoteStorage.widget) {
      remoteStorage.widget = new RemoteStorage.Widget(remoteStorage);
    }
  };

  RemoteStorage.Widget._rs_supported = function(remoteStorage) {
    haveLocalStorage = 'localStorage' in window;
    return true;
  };
var cEl = document.createElement.bind(document);

  function gCl(parent, className) {
    return parent.getElementsByClassName(className)[0];
  }
  function gTl(parent, className) {
    return parent.getElementsByTagName(className)[0];
  }

  function show(el, display) {
    if(typeof(display) === 'undefined') {
      display = 'block';
    }
    el.style.display = display;
    return el;
  }

  function hide(el) {
    show(el,'none');
    return el;
  }

  function removeClass(el, className) {
    return el.classList.remove(className);
  }

  function addClass(el, className) {
    return el.classList.add(className);
  }

  function View() {
    if(typeof(document) === 'undefined') {
      throw "Widget not supported";
    }
    RemoteStorage.eventHandling(this,
                                'connect',
                                'disconnect',
                                'sync',
                                'reconnect',
                                'display',
                                'reset');

    this.display = function() {
      function toggle_bubble(event) {
        if(bubble.className.search('hidden') < 0) {
          hide_bubble(event);
        } else {
          show_bubble(event);
        }
      }

      function hide_bubble(){
        //console.log('hide bubble',bubble);
        addClass(bubble, 'hidden')
        document.body.removeEventListener('click', hide_bubble_on_body_click);
      }

      function hide_bubble_on_body_click(event) {
        for(var p = event.target; p != document.body; p = p.parentElement) {
          if(p.id == 'remotestorage-widget') {
            return;
          }
        }
        hide_bubble();
      }

      function show_bubble(event){
        //console.log('show bubble',bubble,event)
        removeClass(bubble, 'hidden');
        if(typeof(event) != 'undefined') {
          stop_propagation(event);
        }
        document.body.addEventListener('click', hide_bubble_on_body_click);
        gTl(bubble,'form').userAddress.focus();
      }

      function stop_propagation(event) {
        if(typeof(event.stopPropagation) == 'function') {
          event.stopPropagation();
        } else {
          event.cancelBubble = true;
        }
      }

      if(typeof(this.widget) !== 'undefined')
        return this.widget;

      var element = cEl('div');
      var style = cEl('style');
      style.innerHTML = RemoteStorage.Assets.widgetCss;

      element.id = "remotestorage-widget";

      element.innerHTML = RemoteStorage.Assets.widget;

      element.appendChild(style);
      document.body.appendChild(element);

      var el;
      //sync button
      el = gCl(element, 'sync');
      gTl(el, 'img').src = RemoteStorage.Assets.syncIcon;
      el.addEventListener('click', this.events.sync.bind(this));

      //disconnect button
      el = gCl(element, 'disconnect');
      gTl(el, 'img').src = RemoteStorage.Assets.disconnectIcon;
      el.addEventListener('click', this.events.disconnect.bind(this));

      //get me out of here
      var el = gCl(element, 'remotestorage-reset').addEventListener('click', this.events.reset.bind(this));
      //connect button
      var cb = gCl(element,'connect');
      gTl(cb, 'img').src = RemoteStorage.Assets.connectIcon;
      cb.addEventListener('click', this.events.connect.bind(this));

      // input
      el = gTl(element, 'form').userAddress;
      el.addEventListener('keyup', function(event) {
        if(event.target.value) cb.removeAttribute('disabled');
        else cb.setAttribute('disabled','disabled');
      });
      if(this.userAddress) {
        el.value = this.userAddress;
      }

      //the cube
      el = gCl(element, 'cube');
      el.src = RemoteStorage.Assets.remoteStorageIcon;
      el.addEventListener('click', toggle_bubble);

      //the bubble
      var bubble = gCl(element,'bubble');
      var bubbleDontCatch = { INPUT: true, BUTTON: true, IMG: true };
      bubble.addEventListener('click', function(event) {
        if(! bubbleDontCatch[event.target.tagName]) {
          show_bubble(event);
        }
      })
      hide_bubble();

      this.div = element;

      this.states.initial.call(this);
      this.events.display.call(this);
      return this.div;
    };

    this.setState = function(state, args) {
      //console.log('setState(',state,',',args,');');
      var s = this.states[state];
      if(typeof(s) === 'undefined') {
        throw new Error("Bad State assigned to view: " + state);
      }
      s.apply(this,args);
    };

    this.setUserAddress = function(addr) {
      this.userAddress = addr;

      var el;
      if(this.div && (el = gTl(this.div, 'form').userAddress)) {
        el.value = this.userAddress;
      }
    };
  }

  View.prototype = {
    // States:
    //  initial      - not connected
    //  authing      - in auth flow
    //  connected    - connected to remote storage, not syncing at the moment
    //  busy         - connected, syncing at the moment
    //  offline      - connected, but no network connectivity
    //  error        - connected, but sync error happened
    //  unauthorized - connected, but request returned 401
    currentState : 'initial',
    states :  {
      initial : function(message) {
        var cube = gCl(this.div, 'cube');
        var bubble = this.div.querySelector('.bubble');
        var info = message || 'This app allows you to use your own storage! Find more info on remotestorage.io';
        if(message) {
          cube.src = RemoteStorage.Assets.remoteStorageIconError;
          removeClass(cube, 'remotestorage-loading');
          bubble.classList.remove('hidden');
          setTimeout(function(){
            cube.src = RemoteStorage.Assets.remoteStorageIcon;
          },3512)
        } else {
          if(! bubble.classList.contains('hidden')) {
            bubble.classList.add('hidden');
          }
        }
        this.div.className = "remotestorage-state-initial";
        gCl(this.div, 'status-text').innerHTML = "Connect remotestorage";

        //if address not empty connect button enabled
        var cb = gCl(this.div, 'connect')
        if(cb.value)
          cb.removeAttribute('disabled');

        var infoEl = gCl(this.div, 'info');
        infoEl.innerHTML = info;

        if(message) {
          infoEl.classList.add('remotestorage-error-info');
        } else {
          infoEl.classList.remove('remotestorage-error-info');
        }

      },
      authing : function() {
        this.div.className = "remotestorage-state-authing";
        gCl(this.div, 'status-text').innerHTML = "Connecting";
        addClass(gCl(this.div, 'cube'), 'remotestorage-loading'); //TODO needs to be undone when is that neccesary
      },
      connected : function() {
        this.div.className = "remotestorage-state-connected";
        gCl(this.div, 'userAddress').innerHTML = this.userAddress;
        var cube = gCl(this.div, 'cube');
        cube.src = RemoteStorage.Assets.remoteStorageIcon;
        removeClass(cube, 'remotestorage-loading');
      },
      busy : function() {
        this.div.className = "remotestorage-state-busy";
        addClass(gCl(this.div, 'cube'), 'remotestorage-loading'); //TODO needs to be undone when is that neccesary
      },
      offline : function() {
        this.div.className = "remotestorage-state-offline";
        gCl(this.div, 'cube').src = RemoteStorage.Assets.remoteStorageIconOffline;
      },
      error : function(err) {
        var errorMsg = err;
        this.div.className = "remotestorage-state-error";

        gCl(this.div, 'bubble-text').innerHTML = 'ERROR'
        if(err instanceof Error) {
          errorMsg = err.message + '\n\n' +
            err.stack;
        }
        gCl(this.div, 'error-msg').textContent = errorMsg;
        gCl(this.div, 'cube').src = RemoteStorage.Assets.remoteStorageIconError;
        gCl(this.div, 'bubble').classList.remove('hidden');
      },
      unauthorized : function() {
        this.div.className = "remotestorage-state-unauthorized";
      }
    },
    events : {
      connect : function(event) {
        event.preventDefault();
        this._emit('connect', gTl(this.div, 'form').userAddress.value);
      },
      sync : function(event) {
        event.preventDefault();
        this._emit('sync');
      },
      disconnect : function(event) {
        event.preventDefault();
        this._emit('disconnect');
      },
      reset : function(event){
        event.preventDefault();
        var result = window.confirm("this will disconnect and erase all your local data, then reload the page, unsynced data will be losst");
        if(result){
          this._emit('reset');
        }
      },
      // FIXME: what are these???
      reconnect : function() {},
      display : function() {
        if(event)
          event.preventDefault();
        this._emit('display');
      }
    }
  };

})(this);
<commit_msg>get rid of reconnect event in view<commit_after>(function(window) {

  var haveLocalStorage;
  var LS_STATE_KEY = "remotestorage:widget:state";
  function stateSetter(widget, state) {
    return function() {
      if(haveLocalStorage) {
        localStorage[LS_STATE_KEY] = state;
      }
      if(widget.view) {
        if(widget.rs.remote) {
          widget.view.setUserAddress(widget.rs.remote.userAddress);
        }
        widget.view.setState(state, arguments);
      }
    };
  }
  function errorsHandler(widget){
    //decided to not store error state
    return function(error){
      if(error instanceof RemoteStorage.DiscoveryError) {
        console.log('discovery failed',  error, '"' + error.message + '"');
        widget.view.setState('initial', [error.message]);
      } else if(error instanceof RemoteStorage.SyncError) {
        widget.view.setState('offline', []);
      } else {
        widget.view.setState('error', [error]);
      }
    }
  }
  RemoteStorage.Widget = function(remoteStorage) {
    this.rs = remoteStorage;
    this.rs.on('ready', stateSetter(this, 'connected'));
    this.rs.on('disconnected', stateSetter(this, 'initial'));
    //this.rs.on('connecting', stateSetter(this, 'connecting'))
    this.rs.on('authing', stateSetter(this, 'authing'));
    this.rs.on('sync-busy', stateSetter(this, 'busy'));
    this.rs.on('sync-done', stateSetter(this, 'connected'));
    this.rs.on('error', errorsHandler(this) );
    if(haveLocalStorage) {
      var state = localStorage[LS_STATE_KEY] = state;
      if(state) {
        this._rememberedState = state;
      }
    }
  };

  RemoteStorage.Widget.prototype = {
    display: function() {
      if(! this.view) {
        this.setView(new View());
      }
      this.view.display.apply(this.view, arguments);
      return this;
    },

    setView: function(view) {
      this.view = view;
      this.view.on('connect', this.rs.connect.bind(this.rs));
      this.view.on('disconnect', this.rs.disconnect.bind(this.rs));
      this.view.on('sync', this.rs.sync.bind(this.rs));
      this.view.on('reset', function(){
        this.rs.on('disconnected', document.location.reload.bind(document.location))
        this.rs.disconnect()
      }.bind(this));

      if(this._rememberedState) {
        stateSetter(this, this._rememberedState)();
        delete this._rememberedState;
      }
    }
  };

  RemoteStorage.prototype.displayWidget = function() {
    this.widget.display();
  };

  RemoteStorage.Widget._rs_init = function(remoteStorage) {
    if(! remoteStorage.widget) {
      remoteStorage.widget = new RemoteStorage.Widget(remoteStorage);
    }
  };

  RemoteStorage.Widget._rs_supported = function(remoteStorage) {
    haveLocalStorage = 'localStorage' in window;
    return true;
  };
var cEl = document.createElement.bind(document);

  function gCl(parent, className) {
    return parent.getElementsByClassName(className)[0];
  }
  function gTl(parent, className) {
    return parent.getElementsByTagName(className)[0];
  }

  function show(el, display) {
    if(typeof(display) === 'undefined') {
      display = 'block';
    }
    el.style.display = display;
    return el;
  }

  function hide(el) {
    show(el,'none');
    return el;
  }

  function removeClass(el, className) {
    return el.classList.remove(className);
  }

  function addClass(el, className) {
    return el.classList.add(className);
  }

  function View() {
    if(typeof(document) === 'undefined') {
      throw "Widget not supported";
    }
    RemoteStorage.eventHandling(this,
                                'connect',
                                'disconnect',
                                'sync',
                                'display',
                                'reset');

    this.display = function() {
      function toggle_bubble(event) {
        if(bubble.className.search('hidden') < 0) {
          hide_bubble(event);
        } else {
          show_bubble(event);
        }
      }

      function hide_bubble(){
        //console.log('hide bubble',bubble);
        addClass(bubble, 'hidden')
        document.body.removeEventListener('click', hide_bubble_on_body_click);
      }

      function hide_bubble_on_body_click(event) {
        for(var p = event.target; p != document.body; p = p.parentElement) {
          if(p.id == 'remotestorage-widget') {
            return;
          }
        }
        hide_bubble();
      }

      function show_bubble(event){
        //console.log('show bubble',bubble,event)
        removeClass(bubble, 'hidden');
        if(typeof(event) != 'undefined') {
          stop_propagation(event);
        }
        document.body.addEventListener('click', hide_bubble_on_body_click);
        gTl(bubble,'form').userAddress.focus();
      }

      function stop_propagation(event) {
        if(typeof(event.stopPropagation) == 'function') {
          event.stopPropagation();
        } else {
          event.cancelBubble = true;
        }
      }

      if(typeof(this.widget) !== 'undefined')
        return this.widget;

      var element = cEl('div');
      var style = cEl('style');
      style.innerHTML = RemoteStorage.Assets.widgetCss;

      element.id = "remotestorage-widget";

      element.innerHTML = RemoteStorage.Assets.widget;

      element.appendChild(style);
      document.body.appendChild(element);

      var el;
      //sync button
      el = gCl(element, 'sync');
      gTl(el, 'img').src = RemoteStorage.Assets.syncIcon;
      el.addEventListener('click', this.events.sync.bind(this));

      //disconnect button
      el = gCl(element, 'disconnect');
      gTl(el, 'img').src = RemoteStorage.Assets.disconnectIcon;
      el.addEventListener('click', this.events.disconnect.bind(this));

      //get me out of here
      var el = gCl(element, 'remotestorage-reset').addEventListener('click', this.events.reset.bind(this));
      //connect button
      var cb = gCl(element,'connect');
      gTl(cb, 'img').src = RemoteStorage.Assets.connectIcon;
      cb.addEventListener('click', this.events.connect.bind(this));

      // input
      el = gTl(element, 'form').userAddress;
      el.addEventListener('keyup', function(event) {
        if(event.target.value) cb.removeAttribute('disabled');
        else cb.setAttribute('disabled','disabled');
      });
      if(this.userAddress) {
        el.value = this.userAddress;
      }

      //the cube
      el = gCl(element, 'cube');
      el.src = RemoteStorage.Assets.remoteStorageIcon;
      el.addEventListener('click', toggle_bubble);

      //the bubble
      var bubble = gCl(element,'bubble');
      var bubbleDontCatch = { INPUT: true, BUTTON: true, IMG: true };
      bubble.addEventListener('click', function(event) {
        if(! bubbleDontCatch[event.target.tagName]) {
          show_bubble(event);
        }
      })
      hide_bubble();

      this.div = element;

      this.states.initial.call(this);
      this.events.display.call(this);
      return this.div;
    };

    this.setState = function(state, args) {
      //console.log('setState(',state,',',args,');');
      var s = this.states[state];
      if(typeof(s) === 'undefined') {
        throw new Error("Bad State assigned to view: " + state);
      }
      s.apply(this,args);
    };

    this.setUserAddress = function(addr) {
      this.userAddress = addr;

      var el;
      if(this.div && (el = gTl(this.div, 'form').userAddress)) {
        el.value = this.userAddress;
      }
    };
  }

  View.prototype = {
    // States:
    //  initial      - not connected
    //  authing      - in auth flow
    //  connected    - connected to remote storage, not syncing at the moment
    //  busy         - connected, syncing at the moment
    //  offline      - connected, but no network connectivity
    //  error        - connected, but sync error happened
    //  unauthorized - connected, but request returned 401
    currentState : 'initial',
    states :  {
      initial : function(message) {
        var cube = gCl(this.div, 'cube');
        var bubble = this.div.querySelector('.bubble');
        var info = message || 'This app allows you to use your own storage! Find more info on remotestorage.io';
        if(message) {
          cube.src = RemoteStorage.Assets.remoteStorageIconError;
          removeClass(cube, 'remotestorage-loading');
          bubble.classList.remove('hidden');
          setTimeout(function(){
            cube.src = RemoteStorage.Assets.remoteStorageIcon;
          },3512)
        } else {
          if(! bubble.classList.contains('hidden')) {
            bubble.classList.add('hidden');
          }
        }
        this.div.className = "remotestorage-state-initial";
        gCl(this.div, 'status-text').innerHTML = "Connect remotestorage";

        //if address not empty connect button enabled
        var cb = gCl(this.div, 'connect')
        if(cb.value)
          cb.removeAttribute('disabled');

        var infoEl = gCl(this.div, 'info');
        infoEl.innerHTML = info;

        if(message) {
          infoEl.classList.add('remotestorage-error-info');
        } else {
          infoEl.classList.remove('remotestorage-error-info');
        }

      },
      authing : function() {
        this.div.className = "remotestorage-state-authing";
        gCl(this.div, 'status-text').innerHTML = "Connecting";
        addClass(gCl(this.div, 'cube'), 'remotestorage-loading'); //TODO needs to be undone when is that neccesary
      },
      connected : function() {
        this.div.className = "remotestorage-state-connected";
        gCl(this.div, 'userAddress').innerHTML = this.userAddress;
        var cube = gCl(this.div, 'cube');
        cube.src = RemoteStorage.Assets.remoteStorageIcon;
        removeClass(cube, 'remotestorage-loading');
      },
      busy : function() {
        this.div.className = "remotestorage-state-busy";
        addClass(gCl(this.div, 'cube'), 'remotestorage-loading'); //TODO needs to be undone when is that neccesary
      },
      offline : function() {
        this.div.className = "remotestorage-state-offline";
        gCl(this.div, 'cube').src = RemoteStorage.Assets.remoteStorageIconOffline;
      },
      error : function(err) {
        var errorMsg = err;
        this.div.className = "remotestorage-state-error";

        gCl(this.div, 'bubble-text').innerHTML = 'ERROR'
        if(err instanceof Error) {
          errorMsg = err.message + '\n\n' +
            err.stack;
        }
        gCl(this.div, 'error-msg').textContent = errorMsg;
        gCl(this.div, 'cube').src = RemoteStorage.Assets.remoteStorageIconError;
        gCl(this.div, 'bubble').classList.remove('hidden');
      },
      unauthorized : function() {
        this.div.className = "remotestorage-state-unauthorized";
      }
    },
    events : {
      connect : function(event) {
        event.preventDefault();
        this._emit('connect', gTl(this.div, 'form').userAddress.value);
      },
      sync : function(event) {
        event.preventDefault();
        this._emit('sync');
      },
      disconnect : function(event) {
        event.preventDefault();
        this._emit('disconnect');
      },
      reset : function(event){
        event.preventDefault();
        var result = window.confirm("this will disconnect and erase all your local data, then reload the page, unsynced data will be losst");
        if(result){
          this._emit('reset');
        }
      },
      display : function() {
        if(event)
          event.preventDefault();
        this._emit('display');
      }
    }
  };

})(this);
<|endoftext|>


<commit_before>/**
 * Created by huangxinghui on 2015/5/15.
 */

var $ = require('jquery');
var _ = require('underscore');
var Class = require('./clazz');
var delegateEventSplitter = /^(\S+)\s*(.*)$/;

module.exports = Class.extend({
    options: null,
    events: null,

    init: function (element, options) {
        this.$element = $(element);
        this.options = $.extend({}, this.options, this.$element.data(), options);
        this.bindings = $();

        this._create();
        this._on(this.events);
    },

    _create: $.noop,

    _destroy: $.noop,

    _on: function (element, events) {
        if (!events) {
            events = element;
            element = this.$element;
        }

        if (element !== this.$element)
            this.bindings.add(element);

        var key, method, match;
        for (key in events) {
            method = events[key];
            if (!_.isFunction(method)) method = this[events[key]];
            if (!method) continue;
            match = key.match(delegateEventSplitter);
            element.on(match[1] + '.' + this.widgetName, match[2], _.bind(method, this));
        }
    },

    _off: function (element, eventName) {
        eventName = (eventName || "").split(" ").join(this.widgetName + " ") + this.widgetName;
        element.off(eventName);

        this.bindings = $(this.bindings.not(element).get());
    },

    trigger: function (type, data) {
        var e = $.Event((this.widgetName + ':' + type).toLowerCase());
        this.$element.trigger(e, data);
        return e;
    },

    destroy: function () {
        this._destroy();

        this.$element.off('.' + this.widgetName)
            .removeData(this.widgetName);
        this.bindings.off('.' + this.widgetName);
        this.bindings = $();
    }
});<commit_msg>add eventNameSpace in widget class<commit_after>/**
 * Created by huangxinghui on 2015/5/15.
 */

var $ = require('jquery');
var _ = require('underscore');
var Class = require('./clazz');
var delegateEventSplitter = /^(\S+)\s*(.*)$/;

module.exports = Class.extend({
    options: null,
    events: null,

    init: function (element, options) {
        this.$element = $(element);
        this.options = $.extend({}, this.options, this.$element.data(), options);
        this.bindings = $();
        this.eventNamespace = "." + this.widgetName;

        this._create();
        this._on(this.events);
    },

    _create: $.noop,

    _destroy: $.noop,

    _on: function (element, events) {
        if (!events) {
            events = element;
            element = this.$element;
        }

        if (element !== this.$element)
            this.eventNamespacebindings.add(element);

        var key, method, match;
        for (key in events) {
            method = events[key];
            if (!_.isFunction(method)) method = this[events[key]];
            if (!method) continue;
            match = key.match(delegateEventSplitter);
            element.on(match[1] + this.eventNamespace, match[2], _.bind(method, this));
        }
    },

    _off: function (element, eventName) {
        eventName = (eventName || "").split(" ").join(this.eventNamespace + " ") + this.eventNamespace;
        element.off(eventName);

        this.bindings = $(this.bindings.not(element).get());
    },

    trigger: function (type, data) {
        var e = $.Event((this.widgetName + ':' + type).toLowerCase());
        this.$element.trigger(e, data);
        return e;
    },

    destroy: function () {
        this._destroy();

        this.$element.off(this.eventNamespace)
            .removeData(this.widgetName);
        this.bindings.off(this.eventNamespace);
        this.bindings = $();
    }
});<|endoftext|>