<commit_before>/**
 * @author: @AngularClass
 */

const helpers = require('./helpers');
const webpackMerge = require('webpack-merge'); // used to merge webpack configs
// const webpackMergeDll = webpackMerge.strategy({plugins: 'replace'});
const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev

/**
 * Webpack Plugins
 */
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const NamedModulesPlugin = require('webpack/lib/NamedModulesPlugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin');
const ProvidePlugin = require('webpack/lib/ProvidePlugin');

/**
 * Webpack Constants
 */
const ENV = process.env.ENV = process.env.NODE_ENV = 'development';
const HOST = process.env.HOST || 'localhost';
const PORT = process.env.PORT || 3000;
const PUBLIC = process.env.PUBLIC_DEV || HOST + ':' + PORT;
const AOT = process.env.BUILD_AOT || helpers.hasNpmFlag('aot');
const HMR = helpers.hasProcessFlag('hot');
const METADATA = {
    host: HOST,
    port: PORT,
    public: PUBLIC,
    ENV: ENV,
    HMR: HMR,
    AOT: AOT
};

// const DllBundlesPlugin = require('webpack-dll-bundles-plugin').DllBundlesPlugin;

/**
 * Webpack configuration
 *
 * See: http://webpack.github.io/docs/configuration.html#cli
 */
module.exports = function(options) {
    return webpackMerge(commonConfig({ env: ENV }), {

        /**
         * Developer tool to enhance debugging
         *
         * See: http://webpack.github.io/docs/configuration.html#devtool
         * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
         */
        devtool: 'cheap-module-source-map',

        /**
         * Options affecting the output of the compilation.
         *
         * See: http://webpack.github.io/docs/configuration.html#output
         */
        output: {

            /**
             * The output directory as absolute path (required).
             *
             * See: http://webpack.github.io/docs/configuration.html#output-path
             */
            path: helpers.root('dist'),

            /**
             * Specifies the name of each output file on disk.
             * IMPORTANT: You must not specify an absolute path here!
             *
             * See: http://webpack.github.io/docs/configuration.html#output-filename
             */
            filename: '[name].bundle.js',

            /**
             * The filename of the SourceMaps for the JavaScript files.
             * They are inside the output.path directory.
             *
             * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
             */
            sourceMapFilename: '[file].map',

            /** The filename of non-entry chunks as relative path
             * inside the output.path directory.
             *
             * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
             */
            chunkFilename: '[id].chunk.js',

            library: 'ac_[name]',
            libraryTarget: 'var',

            // publicPath: '/RecipeDetails/prod/',
            publicPath: '/'

        },

        module: {

            rules: [

                /**
                 * Css loader support for *.css files (styles directory only)
                 * Loads external css styles into the DOM, supports HMR
                 *
                 */
                {
                    test: /\.css$/,
                    use: ['style-loader', 'css-loader'],
                    include: [helpers.root('src', 'styles')]
                },

                /**
                 * Sass loader support for *.scss files (styles directory only)
                 * Loads external sass styles into the DOM, supports HMR
                 *
                 */
                {
                    test: /\.scss$/,
                    use: ['style-loader', 'css-loader', 'sass-loader'],
                    include: [helpers.root('src', 'styles')]
                },

            ]

        },

        plugins: [

            /**
             * Plugin: DefinePlugin
             * Description: Define free variables.
             * Useful for having development builds with debug logging or adding global constants.
             *
             * Environment helpers
             *
             * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
             *
             * NOTE: when adding more properties, make sure you include them in custom-typings.d.ts
             */
            new DefinePlugin({
                'ENV': JSON.stringify(METADATA.ENV),
                'HMR': METADATA.HMR,
                'process.env.ENV': JSON.stringify(METADATA.ENV),
                'process.env.NODE_ENV': JSON.stringify(METADATA.ENV),
                'process.env.HMR': METADATA.HMR
            }),

            // new DllBundlesPlugin({
            //   bundles: {
            //     polyfills: [
            //       'core-js',
            //       {
            //         name: 'zone.js',
            //         path: 'zone.js/dist/zone.js'
            //       },
            //       {
            //         name: 'zone.js',
            //         path: 'zone.js/dist/long-stack-trace-zone.js'
            //       },
            //     ],
            //     vendor: [
            //       '@angular/platform-browser',
            //       '@angular/platform-browser-dynamic',
            //       '@angular/core',
            //       '@angular/common',
            //       '@angular/forms',
            //       '@angular/http',
            //       '@angular/router',
            //       '@angularclass/hmr',
            //       'rxjs',
            //     ]
            //   },
            //   dllDir: helpers.root('dll'),
            //   webpackConfig: webpackMergeDll(commonConfig({env: ENV}), {
            //     devtool: 'cheap-module-source-map',
            //     plugins: []
            //   })
            // }),

            /**
             * Plugin: AddAssetHtmlPlugin
             * Description: Adds the given JS or CSS file to the files
             * Webpack knows about, and put it into the list of assets
             * html-webpack-plugin injects into the generated html.
             *
             * See: https://github.com/SimenB/add-asset-html-webpack-plugin
             */
            // new AddAssetHtmlPlugin([
            //   { filepath: helpers.root(`dll/${DllBundlesPlugin.resolveFile('polyfills')}`) },
            //   { filepath: helpers.root(`dll/${DllBundlesPlugin.resolveFile('vendor')}`) }
            // ]),

            /**
             * Plugin: NamedModulesPlugin (experimental)
             * Description: Uses file names as module name.
             *
             * See: https://github.com/webpack/webpack/commit/a04ffb928365b19feb75087c63f13cadfc08e1eb
             */
            // new NamedModulesPlugin(),

            /**
             * Plugin LoaderOptionsPlugin (experimental)
             *
             * See: https://gist.github.com/sokra/27b24881210b56bbaff7
             */
            new LoaderOptionsPlugin({
                debug: true,
                options: {

                }
            }),

            new HotModuleReplacementPlugin(),

            new ProvidePlugin({
                jQuery: 'jquery',
                $: 'jquery',
                'window.jQuery': 'jquery',
                Hammer: "hammerjs/hammer"
            }),
        ],

        /**
         * Webpack Development Server configuration
         * Description: The webpack-dev-server is a little node.js Express server.
         * The server emits information about the compilation state to the client,
         * which reacts to those events.
         *
         * See: https://webpack.github.io/docs/webpack-dev-server.html
         */
        devServer: {
            port: METADATA.port,
            host: METADATA.host,
            hot: METADATA.HMR,
            public: METADATA.public,
            historyApiFallback: true,
            watchOptions: {
                // if you're using Docker you may need this
                // aggregateTimeout: 300,
                // poll: 1000,
                ignored: /node_modules/
            },
            /**
             * Here you can access the Express app object and add your own custom middleware to it.
             *
             * See: https://webpack.github.io/docs/webpack-dev-server.html
             */
            setup: function(app) {
                // For example, to define custom handlers for some paths:
                // app.get('/some/path', function(req, res) {
                //   res.json({ custom: 'response' });
                // });
            }
        },

        /**
         * Include polyfills or mocks for various node stuff
         * Description: Node configuration
         *
         * See: https://webpack.github.io/docs/configuration.html#node
         */
        node: {
            global: true,
            crypto: 'empty',
            process: true,
            module: false,
            clearImmediate: false,
            setImmediate: false
        },

        externals: [{
            'materialize-css': 'Materialize',
            jquery: 'jQuery',
        }],
    });
}<commit_msg>del publicPath?;<commit_after>/**
 * @author: @AngularClass
 */

const helpers = require('./helpers');
const webpackMerge = require('webpack-merge'); // used to merge webpack configs
// const webpackMergeDll = webpackMerge.strategy({plugins: 'replace'});
const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev

/**
 * Webpack Plugins
 */
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const NamedModulesPlugin = require('webpack/lib/NamedModulesPlugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin');
const ProvidePlugin = require('webpack/lib/ProvidePlugin');

/**
 * Webpack Constants
 */
const ENV = process.env.ENV = process.env.NODE_ENV = 'development';
const HOST = process.env.HOST || 'localhost';
const PORT = process.env.PORT || 3000;
const PUBLIC = process.env.PUBLIC_DEV || HOST + ':' + PORT;
const AOT = process.env.BUILD_AOT || helpers.hasNpmFlag('aot');
const HMR = helpers.hasProcessFlag('hot');
const METADATA = {
    host: HOST,
    port: PORT,
    public: PUBLIC,
    ENV: ENV,
    HMR: HMR,
    AOT: AOT
};

// const DllBundlesPlugin = require('webpack-dll-bundles-plugin').DllBundlesPlugin;

/**
 * Webpack configuration
 *
 * See: http://webpack.github.io/docs/configuration.html#cli
 */
module.exports = function(options) {
    return webpackMerge(commonConfig({ env: ENV }), {

        /**
         * Developer tool to enhance debugging
         *
         * See: http://webpack.github.io/docs/configuration.html#devtool
         * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps
         */
        devtool: 'cheap-module-source-map',

        /**
         * Options affecting the output of the compilation.
         *
         * See: http://webpack.github.io/docs/configuration.html#output
         */
        output: {

            /**
             * The output directory as absolute path (required).
             *
             * See: http://webpack.github.io/docs/configuration.html#output-path
             */
            path: helpers.root('dist'),

            /**
             * Specifies the name of each output file on disk.
             * IMPORTANT: You must not specify an absolute path here!
             *
             * See: http://webpack.github.io/docs/configuration.html#output-filename
             */
            filename: '[name].bundle.js',

            /**
             * The filename of the SourceMaps for the JavaScript files.
             * They are inside the output.path directory.
             *
             * See: http://webpack.github.io/docs/configuration.html#output-sourcemapfilename
             */
            sourceMapFilename: '[file].map',

            /** The filename of non-entry chunks as relative path
             * inside the output.path directory.
             *
             * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename
             */
            chunkFilename: '[id].chunk.js',

            library: 'ac_[name]',
            libraryTarget: 'var',
        },

        module: {

            rules: [

                /**
                 * Css loader support for *.css files (styles directory only)
                 * Loads external css styles into the DOM, supports HMR
                 *
                 */
                {
                    test: /\.css$/,
                    use: ['style-loader', 'css-loader'],
                    include: [helpers.root('src', 'styles')]
                },

                /**
                 * Sass loader support for *.scss files (styles directory only)
                 * Loads external sass styles into the DOM, supports HMR
                 *
                 */
                {
                    test: /\.scss$/,
                    use: ['style-loader', 'css-loader', 'sass-loader'],
                    include: [helpers.root('src', 'styles')]
                },

            ]

        },

        plugins: [

            /**
             * Plugin: DefinePlugin
             * Description: Define free variables.
             * Useful for having development builds with debug logging or adding global constants.
             *
             * Environment helpers
             *
             * See: https://webpack.github.io/docs/list-of-plugins.html#defineplugin
             *
             * NOTE: when adding more properties, make sure you include them in custom-typings.d.ts
             */
            new DefinePlugin({
                'ENV': JSON.stringify(METADATA.ENV),
                'HMR': METADATA.HMR,
                'process.env.ENV': JSON.stringify(METADATA.ENV),
                'process.env.NODE_ENV': JSON.stringify(METADATA.ENV),
                'process.env.HMR': METADATA.HMR
            }),

            // new DllBundlesPlugin({
            //   bundles: {
            //     polyfills: [
            //       'core-js',
            //       {
            //         name: 'zone.js',
            //         path: 'zone.js/dist/zone.js'
            //       },
            //       {
            //         name: 'zone.js',
            //         path: 'zone.js/dist/long-stack-trace-zone.js'
            //       },
            //     ],
            //     vendor: [
            //       '@angular/platform-browser',
            //       '@angular/platform-browser-dynamic',
            //       '@angular/core',
            //       '@angular/common',
            //       '@angular/forms',
            //       '@angular/http',
            //       '@angular/router',
            //       '@angularclass/hmr',
            //       'rxjs',
            //     ]
            //   },
            //   dllDir: helpers.root('dll'),
            //   webpackConfig: webpackMergeDll(commonConfig({env: ENV}), {
            //     devtool: 'cheap-module-source-map',
            //     plugins: []
            //   })
            // }),

            /**
             * Plugin: AddAssetHtmlPlugin
             * Description: Adds the given JS or CSS file to the files
             * Webpack knows about, and put it into the list of assets
             * html-webpack-plugin injects into the generated html.
             *
             * See: https://github.com/SimenB/add-asset-html-webpack-plugin
             */
            // new AddAssetHtmlPlugin([
            //   { filepath: helpers.root(`dll/${DllBundlesPlugin.resolveFile('polyfills')}`) },
            //   { filepath: helpers.root(`dll/${DllBundlesPlugin.resolveFile('vendor')}`) }
            // ]),

            /**
             * Plugin: NamedModulesPlugin (experimental)
             * Description: Uses file names as module name.
             *
             * See: https://github.com/webpack/webpack/commit/a04ffb928365b19feb75087c63f13cadfc08e1eb
             */
            // new NamedModulesPlugin(),

            /**
             * Plugin LoaderOptionsPlugin (experimental)
             *
             * See: https://gist.github.com/sokra/27b24881210b56bbaff7
             */
            new LoaderOptionsPlugin({
                debug: true,
                options: {

                }
            }),

            new HotModuleReplacementPlugin(),

            new ProvidePlugin({
                jQuery: 'jquery',
                $: 'jquery',
                'window.jQuery': 'jquery',
                Hammer: "hammerjs/hammer"
            }),
        ],

        /**
         * Webpack Development Server configuration
         * Description: The webpack-dev-server is a little node.js Express server.
         * The server emits information about the compilation state to the client,
         * which reacts to those events.
         *
         * See: https://webpack.github.io/docs/webpack-dev-server.html
         */
        devServer: {
            port: METADATA.port,
            host: METADATA.host,
            hot: METADATA.HMR,
            public: METADATA.public,
            historyApiFallback: true,
            watchOptions: {
                // if you're using Docker you may need this
                // aggregateTimeout: 300,
                // poll: 1000,
                ignored: /node_modules/
            },
            /**
             * Here you can access the Express app object and add your own custom middleware to it.
             *
             * See: https://webpack.github.io/docs/webpack-dev-server.html
             */
            setup: function(app) {
                // For example, to define custom handlers for some paths:
                // app.get('/some/path', function(req, res) {
                //   res.json({ custom: 'response' });
                // });
            }
        },

        /**
         * Include polyfills or mocks for various node stuff
         * Description: Node configuration
         *
         * See: https://webpack.github.io/docs/configuration.html#node
         */
        node: {
            global: true,
            crypto: 'empty',
            process: true,
            module: false,
            clearImmediate: false,
            setImmediate: false
        },

        externals: [{
            'materialize-css': 'Materialize',
            jquery: 'jQuery',
        }],
    });
}<|endoftext|>


<commit_before>var pow = (Math.pow(2, 14) - 1);

function getHumid(buf) {
  var data = buf[0];
  return (((data[0] & 0x3f) << 8) | data[1]) * 100 / pow;
}
function getTemp(buf) {
   var data = buf[0];
   return ((data[2] << 6) + (data[3] >> 2)) / pow * 165 - 40;
}

function getHumidTemp(buf) {
  return {
    humidity: getHumid(buf),
   temperature: getTemp(buf)
  }
}

module.exports = {
    "name":"watch",
    "gpio-path": "tests/gpio-test/class/gpio",
    "i2c-bus": 1,
    "components" : [
       {"type": "link", name: "HiH-6130", "address": 0x27, "interface": "i2c",
       "get": [
          {"type": "read", "cmd": 0, val: new Buffer(4)}
         ], formatOutput: getHumidTemp
       },
      {"type": "temperature", "link": "HiH-6130", "returnAs": "temperature"},
      {"type": "humidity", "link": "HiH-6130", "returnAs": "humidity"},
      {"type": "button", "address": 18, "direction": "in", "edge": "both", "interface": "gpio",
       "debounce": 100}
    ]
}
<commit_msg>updated watch file<commit_after>var pow = (Math.pow(2, 14) - 1);

function getHumid(buf) {
  var data = buf[0];
  return (((data[0] & 0x3f) << 8) | data[1]) * 100 / pow;
}
function getTemp(buf) {
   var data = buf[0];
   return ((data[2] << 6) + (data[3] >> 2)) / pow * 165 - 40;
}

function getHumidTemp(buf) {
  return {
    humidity: getHumid(buf),
   temperature: getTemp(buf)
  }
}

module.exports = {
    "name":"watch",
    "i2c-bus": 1,
    "components" : [
       {"type": "link", name: "HiH-6130", "address": 0x27, "interface": "i2c",
       "get": [
          {"type": "read", "cmd": 0, val: new Buffer(4)}
         ], formatOutput: getHumidTemp
       },
      {"type": "temperature", "link": "HiH-6130", "returnAs": "temperature"},
      {"type": "humidity", "link": "HiH-6130", "returnAs": "humidity"},
      {"type": "button", "address": 18, "direction": "in", "edge": "both", "interface": "gpio",
       "debounce": 100}
    ]
}
<|endoftext|>


<commit_before>/* This module uses a give ip to visit the whole urls in the bucket assigned to it
*/
'use strict';

module.exports = function(bucketExplorer , database) {
	//
    var ObjectId = require('mongodb').ObjectId;
	var Spooky = require('spooky');
    var EventEmitter = require('events').EventEmitter;
    var domain = require('domain');

	var bucket;
    var ipQueue = [];
    var ipQueueIndex = 0;
    var child_processes = 0;

    //
    var Buckets = database.model('Buckets');

    //
    var setBucket =  function(bucketObj){
    	 bucket = bucketObj;
         if(bucket.urls.length>0){
            for(var i=0; i<bucket.urls.length; i++){
                bucket.urls[i].visited = 0;
                bucket.urls[i].statusText = 'No status yet';
            };
         }

    	 console.log(bucket);
    	 console.log('bucket set in visitor');
         startUpdateDaemon();
    };

    //
    var getBucket = function(){
    	return bucket;
    };

    //
    var updateBucket = function(bucketObj , meta){
    	console.log(meta);
    	if(bucket){
            if(bucketObj._id+'' == bucket._id){
	           if(meta.action == 0){
	           	   console.log('Deleting url in this bucket');
                   bucket.urls.splice(meta.index , 1);
	           }
	           else if(meta.action == 1) {
                   console.log('Updating url in this bucket');
                   bucket = bucketObj;
	           }
	    	}
	    	else{
	    	   console.log('Just passing by');
	    	}
    	}
    	else{
    		 console.log('Bucket empty here');
    	}
    }

    //
    var notifyDelete = function(_id){
         console.log('Bucket with'+ _id +'deleted');
         if(bucket){
             if(bucket._id == _id){
                console.log('This bucket was deleted');
                setTimeout(function(){
                    process.exit(0);
                } , 10000);
             }
             else{
                 console.log('Not this one 1..');
             }

         }
         else{
            console.log('Not this one..');
         }
    }

    //
    var visitWith = function(ip){
        console.log('Adding %s to queue' , ip);
        if(ipQueue.indexOf(ip)<0){
            ipQueue.push(ip);
        }
        else{
            console.log('ip alredy used or currently in use');
        }

        if(ipQueue.length == 1){
            startVisitingDaemon();
        }
    }

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    var V_WORKER = function(){
        var workerEvents = new EventEmitter;

        var visit = function(ip , urlsArr){
            console.log('visit starting with '+ip+' and '+urlsArr.length+' urls');

            let spooky = Spooky.create({
                child: {
                    transport: 'http',
                    proxy: ip
                },

                casper: {
                    logLevel: 'debug',
                    verbose: true,
                    options: {
                        clientScripts: ['public/js/vendors/jquery.min.js'],
                        pageSettings: {
                            webSecurityEnabled: false
                        }
                    }
                }
            },
            function(err){
               if (err) {
                    e = new Error('Failed to initialize SpookyJS');
                    e.details = err;
                    throw e;
                }

                //
                for(let i=0; i < urlsArr.length; i++){
                    (function(url , selector , index){
                        //
                        spooky.start();
                        spooky.then(function () {
                            this.page.customHeaders = {
                                "Referer": 'https://www.google.com'
                            };
                        });
                        spooky.thenOpen(url);
                        spooky.then([{url:url , selector:selector , index:index} , function(){
                            //
                            this.done = function(err , status){
                                if(err){
                                    this.emit('done', {status:this.getCurrentUrl() , index:index});
                                    return phantom.clearCookies();
                                }
                                else{
                                    this.emit('done', {status:this.getCurrentUrl() , index:index});
                                    return phantom.clearCookies();
                                }
                            }

                            if(selector=='none'){
                                this.then(function(){
                                    this.wait(15000 , function(){
                                        this.done(null , true);
                                    });
                                });
                            }

                            else{
                                this.then(function(){
                                    this.waitForSelector(selector , function(){
                                        this.thenClick(selector , function() {
                                        this.done(null , true);
                                        });

                                    } , function(){
                                        this.done(true , null);
                                    } , 20000);
                                });
                            }
                        }]);
                    })(urlsArr[i].urlName , urlsArr[i].selector , i);
                }

                //
                spooky.run();
            });

            //
            spooky.on('console', function (line) {
                console.log(line);
            });

            //
            spooky.on('error', function (e, stack) {
                console.error(stack||e);
                workerEvents.emit('done' , {status:stack?stack:e , index:0});
            });

            //
            spooky.on('done', function (status) {
                workerEvents.emit('done' , status);
            });

            //self destruct this instance in 15 minutes
            setTimeout(function(){
                console.log('Instance destroyed');
                spooky.destroy();
                child_processes--;
            } , 5*60000);
        };

        return {
            visit:visit,
            status:workerEvents
        }
    }
    //++++++++++++++++++++++++++++++++END++++++++++++++++++++++++++++++++++++++++++

    //updateBucket after every 120 secs of activity
    function startUpdateDaemon(){
        var timer = 0;
        console.log('Starting cron daemon');
        setInterval(function(){
            bucket.lastActive = Date.now()+'';
            Buckets.update(
                {_id : ObjectId(bucket._id)},
                bucket,
                function(err , result){
                    if(err){
                        console.log(err);
                        res.status(500).send('Database error during cron update in visitor');
                    }
                    else {
                        timer+=2;
                        if(timer >= 122){
                            console.log('Maximum uptime of two hours exceeded exiting....');
                            process.exit(0);
                        }
                        console.log('bucket updated in cron job');
                    }
                }
          );
        } , 120000);
    }

    //
    function startVisitingDaemon(){
       let visiting = 0;
       let limit =  20;

       let v_worker = V_WORKER();

       function fillVisiting(){
            console.log('fill visiting called');
            if(ipQueueIndex < ipQueue.length){
               child_processes++;
               console.log(child_processes+' child_processes currently running');
               v_worker.visit(ipQueue[ipQueueIndex] , bucket.urls);
               ipQueueIndex++;
               visiting+= bucket.urls.length;
            }
            else{
                if(limit < visiting){
                    console.log('Visiting urls have exceeded the limit');
                    limit+=100;
                }
                else{
                    console.log('Good ip shortage');
                }
            }

            //
            setTimeout(function(){
                return fillVisiting();
            } , 10000);
       }

      //
      fillVisiting();

      //
      v_worker.status.on('done' , function(status){
            console.log(status);
            bucket.urls[status.index].statusText = status.status;
            bucket.urls[status.index].visited++;
            visiting--;
            limit--;
        });
    }

	return {
	    visitWith:visitWith,
	    getBucket:getBucket,
	    setBucket:setBucket,
	    updateBucket:updateBucket,
        notifyDelete:notifyDelete
	}
};<commit_msg>Updated test selector<commit_after>/* This module uses a give ip to visit the whole urls in the bucket assigned to it
*/
'use strict';

module.exports = function(bucketExplorer , database) {
	//
    var ObjectId = require('mongodb').ObjectId;
	var Spooky = require('spooky');
    var EventEmitter = require('events').EventEmitter;
    var domain = require('domain');

	var bucket;
    var ipQueue = [];
    var ipQueueIndex = 0;
    var child_processes = 0;

    //
    var Buckets = database.model('Buckets');

    //
    var setBucket =  function(bucketObj){
    	 bucket = bucketObj;
         if(bucket.urls.length>0){
            for(var i=0; i<bucket.urls.length; i++){
                bucket.urls[i].visited = 0;
                bucket.urls[i].statusText = 'No status yet';
            };
         }

    	 console.log(bucket);
    	 console.log('bucket set in visitor');
         startUpdateDaemon();
    };

    //
    var getBucket = function(){
    	return bucket;
    };

    //
    var updateBucket = function(bucketObj , meta){
    	console.log(meta);
    	if(bucket){
            if(bucketObj._id+'' == bucket._id){
	           if(meta.action == 0){
	           	   console.log('Deleting url in this bucket');
                   bucket.urls.splice(meta.index , 1);
	           }
	           else if(meta.action == 1) {
                   console.log('Updating url in this bucket');
                   bucket = bucketObj;
	           }
	    	}
	    	else{
	    	   console.log('Just passing by');
	    	}
    	}
    	else{
    		 console.log('Bucket empty here');
    	}
    }

    //
    var notifyDelete = function(_id){
         console.log('Bucket with'+ _id +'deleted');
         if(bucket){
             if(bucket._id == _id){
                console.log('This bucket was deleted');
                setTimeout(function(){
                    process.exit(0);
                } , 10000);
             }
             else{
                 console.log('Not this one 1..');
             }

         }
         else{
            console.log('Not this one..');
         }
    }

    //
    var visitWith = function(ip){
        console.log('Adding %s to queue' , ip);
        if(ipQueue.indexOf(ip)<0){
            ipQueue.push(ip);
        }
        else{
            console.log('ip alredy used or currently in use');
        }

        if(ipQueue.length == 1){
            startVisitingDaemon();
        }
    }

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    var V_WORKER = function(){
        var workerEvents = new EventEmitter;

        var visit = function(ip , urlsArr){
            console.log('visit starting with '+ip+' and '+urlsArr.length+' urls');

            let spooky = Spooky.create({
                child: {
                    transport: 'http',
                    proxy: ip
                },

                casper: {
                    logLevel: 'debug',
                    verbose: true,
                    options: {
                        clientScripts: ['public/js/vendors/jquery.min.js'],
                        pageSettings: {
                            webSecurityEnabled: false
                        }
                    }
                }
            },
            function(err){
               if (err) {
                    e = new Error('Failed to initialize SpookyJS');
                    e.details = err;
                    throw e;
                }

                //
                for(let i=0; i < urlsArr.length; i++){
                    (function(url , selector , index){
                        //
                        spooky.start();
                        spooky.then(function () {
                            this.page.customHeaders = {
                                "Referer": 'https://www.google.com'
                            };
                        });
                        spooky.thenOpen(url);
                        spooky.then([{url:url , selector:selector , index:index} , function(){
                            //
                            this.done = function(err , status){
                                if(err){
                                    this.emit('done', {status:this.getCurrentUrl() , index:index});
                                    return phantom.clearCookies();
                                }
                                else{
                                    this.emit('done', {status:this.getCurrentUrl() , index:index});
                                    return phantom.clearCookies();
                                }
                            }

                            if(selector=='test'){
                                this.then(function(){
                                    this.withFrame(0 ,  function(){
                                        this.thenClick('a' , function(){

                                        });//
                                    });
                                });
                            }
                            else if(selector=='none'){
                                this.then(function(){
                                    this.wait(15000 , function(){
                                        this.done(null , true);
                                    });
                                });
                            }

                            else{
                                this.then(function(){
                                    this.waitForSelector(selector , function(){
                                        this.thenClick(selector , function() {
                                        this.done(null , true);
                                        });

                                    } , function(){
                                        this.done(true , null);
                                    } , 20000);
                                });
                            }
                        }]);
                    })(urlsArr[i].urlName , urlsArr[i].selector , i);
                }

                //
                spooky.run();
            });

            //
            spooky.on('console', function (line) {
                console.log(line);
            });

            //
            spooky.on('error', function (e, stack) {
                console.error(stack||e);
                workerEvents.emit('done' , {status:stack?stack:e , index:0});
            });

            //
            spooky.on('done', function (status) {
                workerEvents.emit('done' , status);
            });

            //self destruct this instance in 15 minutes
            setTimeout(function(){
                console.log('Instance destroyed');
                spooky.destroy();
                child_processes--;
            } , 5*60000);
        };

        return {
            visit:visit,
            status:workerEvents
        }
    }
    //++++++++++++++++++++++++++++++++END++++++++++++++++++++++++++++++++++++++++++

    //updateBucket after every 120 secs of activity
    function startUpdateDaemon(){
        var timer = 0;
        console.log('Starting cron daemon');
        setInterval(function(){
            bucket.lastActive = Date.now()+'';
            Buckets.update(
                {_id : ObjectId(bucket._id)},
                bucket,
                function(err , result){
                    if(err){
                        console.log(err);
                        res.status(500).send('Database error during cron update in visitor');
                    }
                    else {
                        timer+=2;
                        if(timer >= 122){
                            console.log('Maximum uptime of two hours exceeded exiting....');
                            process.exit(0);
                        }
                        console.log('bucket updated in cron job');
                    }
                }
          );
        } , 120000);
    }

    //
    function startVisitingDaemon(){
       let visiting = 0;
       let limit =  20;

       let v_worker = V_WORKER();

       function fillVisiting(){
            console.log('fill visiting called');
            if(ipQueueIndex < ipQueue.length){
               child_processes++;
               console.log(child_processes+' child_processes currently running');
               v_worker.visit(ipQueue[ipQueueIndex] , bucket.urls);
               ipQueueIndex++;
               visiting+= bucket.urls.length;
            }
            else{
                if(limit < visiting){
                    console.log('Visiting urls have exceeded the limit');
                    limit+=100;
                }
                else{
                    console.log('Good ip shortage');
                }
            }

            //
            setTimeout(function(){
                return fillVisiting();
            } , 10000);
       }

      //
      fillVisiting();

      //
      v_worker.status.on('done' , function(status){
            console.log(status);
            bucket.urls[status.index].statusText = status.status;
            bucket.urls[status.index].visited++;
            visiting--;
            limit--;
        });
    }

	return {
	    visitWith:visitWith,
	    getBucket:getBucket,
	    setBucket:setBucket,
	    updateBucket:updateBucket,
        notifyDelete:notifyDelete
	}
};<|endoftext|>


<commit_before>import {
  UPDATE_STATE, SET_STATE, LIFTED_ACTION,
  SELECT_INSTANCE, REMOVE_INSTANCE, TOGGLE_SYNC
} from '../constants/actionTypes';
import { DISCONNECTED } from '../constants/socketActionTypes';
import parseJSON from '../utils/parseJSON';
import { recompute } from '../utils/updateState';

export const initialState = {
  selected: null,
  current: 'default',
  sync: false,
  connections: {},
  options: { default: {} },
  states: {
    default: {
      actionsById: {},
      computedStates: [],
      currentStateIndex: -1,
      nextActionId: 0,
      skippedActionIds: [],
      stagedActionIds: []
    }
  }
};

function updateState(state, request, id, serialize) {
  let payload = request.payload;
  const actionsById = request.actionsById;
  if (actionsById) {
    payload = {
      ...payload,
      actionsById: parseJSON(actionsById, serialize),
      computedStates: parseJSON(request.computedStates, serialize)
    };
    if (request.type === 'STATE' && request.committedState) {
      payload.committedState = payload.computedStates[0].state;
    }
  } else {
    payload = parseJSON(payload, serialize);
  }

  let newState;
  const liftedState = state[id] || state.default;
  const action = request.action && parseJSON(request.action) || {};

  switch (request.type) {
    case 'INIT':
      newState = recompute(
        state.default,
        payload,
        { action: { type: '@@INIT' }, timestamp: action.timestamp || Date.now() }
      );
      break;
    case 'ACTION': {
      let isExcess = request.isExcess;
      const nextActionId = request.nextActionId || (liftedState.nextActionId + 1);
      if (typeof isExcess === 'undefined') isExcess = nextActionId > request.maxAge;
      if (Array.isArray(action)) {
        // Batched actions
        newState = liftedState;
        for (let i = 0; i < action.length; i++) {
          newState = recompute(
            newState,
            request.batched ? payload : payload[i],
            action[i],
            newState.nextActionId + 1,
            isExcess
          );
        }
      } else {
        newState = recompute(
          liftedState,
          payload,
          action,
          nextActionId,
          isExcess
        );
      }
      break;
    }
    case 'STATE':
      newState = payload;
      if (newState.computedStates.length <= newState.currentStateIndex) {
        newState.currentStateIndex = newState.computedStates.length - 1;
      }
      break;
    case 'PARTIAL_STATE':
      const maxAge = request.maxAge;
      const nextActionId = payload.nextActionId;
      const stagedActionIds = payload.stagedActionIds;
      let computedStates = payload.computedStates;
      let oldActionsById;
      let oldComputedStates;
      let committedState;
      if (nextActionId > maxAge) {
        const oldStagedActionIds = liftedState.stagedActionIds;
        const excess = oldStagedActionIds.indexOf(stagedActionIds[1]);
        let key;
        if (excess > 0) {
          oldComputedStates = liftedState.computedStates.slice(excess - 1);
          oldActionsById = { ...liftedState.actionsById };
          for (let i = 1; i < excess; i++) {
            key = oldStagedActionIds[i];
            if (key) delete oldActionsById[key];
          }
          committedState = computedStates[0].state;
        } else {
          oldActionsById = liftedState.actionsById;
          oldComputedStates = liftedState.computedStates;
          committedState = liftedState.committedState;
        }
      } else {
        oldActionsById = liftedState.actionsById;
        oldComputedStates = liftedState.computedStates;
        committedState = liftedState.committedState;
      }
      computedStates = [...oldComputedStates, ...computedStates];
      const statesCount = computedStates.length;
      let currentStateIndex = payload.currentStateIndex;
      if (statesCount <= currentStateIndex) currentStateIndex = statesCount - 1;

      newState = {
        ...liftedState,
        actionsById: { ...oldActionsById, ...payload.actionsById },
        computedStates,
        currentStateIndex,
        nextActionId,
        stagedActionIds,
        committedState
      };
      break;
    case 'LIFTED':
      newState = liftedState;
      break;
    default:
      return state;
  }

  if (request.liftedState) newState = { ...newState, ...request.liftedState };
  return { ...state, [id]: newState };
}

export function dispatchAction(state, { action }) {
  if (action.type === 'JUMP_TO_STATE' || action.type === 'JUMP_TO_ACTION') {
    const id = state.selected || state.current;
    const liftedState = state.states[id];
    let currentStateIndex = action.index;
    if (typeof currentStateIndex === 'undefined' && action.actionId) {
      currentStateIndex = liftedState.stagedActionIds.indexOf(action.actionId);
    }
    return {
      ...state,
      states: {
        ...state.states,
        [id]: { ...liftedState, currentStateIndex }
      }
    };
  }
  return state;
}

function removeState(state, connectionId) {
  const instanceIds = state.connections[connectionId];
  if (!instanceIds) return state;

  const connections = { ...state.connections };
  const options = { ...state.options };
  const states = { ...state.states };
  let selected = state.selected;
  let current = state.current;
  let sync = state.sync;

  delete connections[connectionId];
  instanceIds.forEach(id => {
    if (id === selected) {
      selected = null;
      sync = false;
    }
    if (id === current) {
      const inst = Object.keys(connections)[0];
      if (inst) current = connections[inst][0];
      else current = 'default';
    }
    delete options[id];
    delete states[id];
  });
  return {
    selected,
    current,
    sync,
    connections,
    options,
    states
  };
}

function init({ type, action, name, libConfig = {} }, connectionId, current) {
  let lib;
  let actionCreators;
  let creators = libConfig.actionCreators || action;
  if (typeof creators === 'string') creators = JSON.parse(creators);
  if (Array.isArray(creators)) actionCreators = creators;
  if (type === 'STATE') lib = 'redux';
  return {
    name: libConfig.name || name || current,
    connectionId,
    explicitLib: libConfig.type,
    lib,
    actionCreators,
    features: libConfig.features ? libConfig.features :
      {
        lock: lib === 'redux', export: libConfig.type === 'redux' ? 'custom' : true,
        import: 'custom', persist: true, pause: true, reorder: true, jump: true, skip: true,
        dispatch: true, test: true
      },
    serialize: libConfig.serialize
  };
}

export default function instances(state = initialState, action) {
  switch (action.type) {
    case UPDATE_STATE:
      const { request } = action;
      if (!request) return state;
      const connectionId = action.id || request.id;
      const current = request.instanceId || connectionId;
      let connections = state.connections;
      let options = state.options;

      if (typeof state.options[current] === 'undefined') {
        connections = {
          ...state.connections,
          [connectionId]: [...(connections[connectionId] || []), current]
        };
        options = { ...options, [current]: init(request, connectionId, current) };
      }

      return {
        ...state,
        current,
        connections,
        options,
        states: updateState(state.states, request, current, options[current].serialize)
      };
    case SET_STATE:
      return {
        ...state,
        states: {
          ...state.states,
          [getActiveInstance(state)]: action.newState
        }
      };
    case TOGGLE_SYNC:
      return { ...state, sync: !state.sync };
    case SELECT_INSTANCE:
      return { ...state, selected: action.selected, sync: false };
    case REMOVE_INSTANCE:
      return removeState(state, action.id);
    case LIFTED_ACTION: {
      if (action.message === 'DISPATCH') return dispatchAction(state, action);
      if (action.message === 'IMPORT') {
        const id = state.selected || state.current;
        if (state.options[id].features.import === true) {
          return {
            ...state,
            states: {
              ...state.states,
              [id]: parseJSON(action.state)
            }
          };
        }
      }
      return state;
    }
    case DISCONNECTED:
      return initialState;
    default:
      return state;
  }
}

/* eslint-disable no-shadow */
export const getActiveInstance = instances => instances.selected || instances.current;
/* eslint-enable */
<commit_msg>Support __serializedType__ inside actions (#42)<commit_after>import {
  UPDATE_STATE, SET_STATE, LIFTED_ACTION,
  SELECT_INSTANCE, REMOVE_INSTANCE, TOGGLE_SYNC
} from '../constants/actionTypes';
import { DISCONNECTED } from '../constants/socketActionTypes';
import parseJSON from '../utils/parseJSON';
import { recompute } from '../utils/updateState';

export const initialState = {
  selected: null,
  current: 'default',
  sync: false,
  connections: {},
  options: { default: {} },
  states: {
    default: {
      actionsById: {},
      computedStates: [],
      currentStateIndex: -1,
      nextActionId: 0,
      skippedActionIds: [],
      stagedActionIds: []
    }
  }
};

function updateState(state, request, id, serialize) {
  let payload = request.payload;
  const actionsById = request.actionsById;
  if (actionsById) {
    payload = {
      ...payload,
      actionsById: parseJSON(actionsById, serialize),
      computedStates: parseJSON(request.computedStates, serialize)
    };
    if (request.type === 'STATE' && request.committedState) {
      payload.committedState = payload.computedStates[0].state;
    }
  } else {
    payload = parseJSON(payload, serialize);
  }

  let newState;
  const liftedState = state[id] || state.default;
  const action = request.action && parseJSON(request.action, serialize) || {};

  switch (request.type) {
    case 'INIT':
      newState = recompute(
        state.default,
        payload,
        { action: { type: '@@INIT' }, timestamp: action.timestamp || Date.now() }
      );
      break;
    case 'ACTION': {
      let isExcess = request.isExcess;
      const nextActionId = request.nextActionId || (liftedState.nextActionId + 1);
      if (typeof isExcess === 'undefined') isExcess = nextActionId > request.maxAge;
      if (Array.isArray(action)) {
        // Batched actions
        newState = liftedState;
        for (let i = 0; i < action.length; i++) {
          newState = recompute(
            newState,
            request.batched ? payload : payload[i],
            action[i],
            newState.nextActionId + 1,
            isExcess
          );
        }
      } else {
        newState = recompute(
          liftedState,
          payload,
          action,
          nextActionId,
          isExcess
        );
      }
      break;
    }
    case 'STATE':
      newState = payload;
      if (newState.computedStates.length <= newState.currentStateIndex) {
        newState.currentStateIndex = newState.computedStates.length - 1;
      }
      break;
    case 'PARTIAL_STATE':
      const maxAge = request.maxAge;
      const nextActionId = payload.nextActionId;
      const stagedActionIds = payload.stagedActionIds;
      let computedStates = payload.computedStates;
      let oldActionsById;
      let oldComputedStates;
      let committedState;
      if (nextActionId > maxAge) {
        const oldStagedActionIds = liftedState.stagedActionIds;
        const excess = oldStagedActionIds.indexOf(stagedActionIds[1]);
        let key;
        if (excess > 0) {
          oldComputedStates = liftedState.computedStates.slice(excess - 1);
          oldActionsById = { ...liftedState.actionsById };
          for (let i = 1; i < excess; i++) {
            key = oldStagedActionIds[i];
            if (key) delete oldActionsById[key];
          }
          committedState = computedStates[0].state;
        } else {
          oldActionsById = liftedState.actionsById;
          oldComputedStates = liftedState.computedStates;
          committedState = liftedState.committedState;
        }
      } else {
        oldActionsById = liftedState.actionsById;
        oldComputedStates = liftedState.computedStates;
        committedState = liftedState.committedState;
      }
      computedStates = [...oldComputedStates, ...computedStates];
      const statesCount = computedStates.length;
      let currentStateIndex = payload.currentStateIndex;
      if (statesCount <= currentStateIndex) currentStateIndex = statesCount - 1;

      newState = {
        ...liftedState,
        actionsById: { ...oldActionsById, ...payload.actionsById },
        computedStates,
        currentStateIndex,
        nextActionId,
        stagedActionIds,
        committedState
      };
      break;
    case 'LIFTED':
      newState = liftedState;
      break;
    default:
      return state;
  }

  if (request.liftedState) newState = { ...newState, ...request.liftedState };
  return { ...state, [id]: newState };
}

export function dispatchAction(state, { action }) {
  if (action.type === 'JUMP_TO_STATE' || action.type === 'JUMP_TO_ACTION') {
    const id = state.selected || state.current;
    const liftedState = state.states[id];
    let currentStateIndex = action.index;
    if (typeof currentStateIndex === 'undefined' && action.actionId) {
      currentStateIndex = liftedState.stagedActionIds.indexOf(action.actionId);
    }
    return {
      ...state,
      states: {
        ...state.states,
        [id]: { ...liftedState, currentStateIndex }
      }
    };
  }
  return state;
}

function removeState(state, connectionId) {
  const instanceIds = state.connections[connectionId];
  if (!instanceIds) return state;

  const connections = { ...state.connections };
  const options = { ...state.options };
  const states = { ...state.states };
  let selected = state.selected;
  let current = state.current;
  let sync = state.sync;

  delete connections[connectionId];
  instanceIds.forEach(id => {
    if (id === selected) {
      selected = null;
      sync = false;
    }
    if (id === current) {
      const inst = Object.keys(connections)[0];
      if (inst) current = connections[inst][0];
      else current = 'default';
    }
    delete options[id];
    delete states[id];
  });
  return {
    selected,
    current,
    sync,
    connections,
    options,
    states
  };
}

function init({ type, action, name, libConfig = {} }, connectionId, current) {
  let lib;
  let actionCreators;
  let creators = libConfig.actionCreators || action;
  if (typeof creators === 'string') creators = JSON.parse(creators);
  if (Array.isArray(creators)) actionCreators = creators;
  if (type === 'STATE') lib = 'redux';
  return {
    name: libConfig.name || name || current,
    connectionId,
    explicitLib: libConfig.type,
    lib,
    actionCreators,
    features: libConfig.features ? libConfig.features :
      {
        lock: lib === 'redux', export: libConfig.type === 'redux' ? 'custom' : true,
        import: 'custom', persist: true, pause: true, reorder: true, jump: true, skip: true,
        dispatch: true, test: true
      },
    serialize: libConfig.serialize
  };
}

export default function instances(state = initialState, action) {
  switch (action.type) {
    case UPDATE_STATE:
      const { request } = action;
      if (!request) return state;
      const connectionId = action.id || request.id;
      const current = request.instanceId || connectionId;
      let connections = state.connections;
      let options = state.options;

      if (typeof state.options[current] === 'undefined') {
        connections = {
          ...state.connections,
          [connectionId]: [...(connections[connectionId] || []), current]
        };
        options = { ...options, [current]: init(request, connectionId, current) };
      }

      return {
        ...state,
        current,
        connections,
        options,
        states: updateState(state.states, request, current, options[current].serialize)
      };
    case SET_STATE:
      return {
        ...state,
        states: {
          ...state.states,
          [getActiveInstance(state)]: action.newState
        }
      };
    case TOGGLE_SYNC:
      return { ...state, sync: !state.sync };
    case SELECT_INSTANCE:
      return { ...state, selected: action.selected, sync: false };
    case REMOVE_INSTANCE:
      return removeState(state, action.id);
    case LIFTED_ACTION: {
      if (action.message === 'DISPATCH') return dispatchAction(state, action);
      if (action.message === 'IMPORT') {
        const id = state.selected || state.current;
        if (state.options[id].features.import === true) {
          return {
            ...state,
            states: {
              ...state.states,
              [id]: parseJSON(action.state)
            }
          };
        }
      }
      return state;
    }
    case DISCONNECTED:
      return initialState;
    default:
      return state;
  }
}

/* eslint-disable no-shadow */
export const getActiveInstance = instances => instances.selected || instances.current;
/* eslint-enable */
<|endoftext|>


<commit_before>const list = `
abits
acx
aex.com
allcoin.com
appreciater
appreiator
apreciator
ausbitban
ausbltbank
battrex
bbittrex
bbuildawhale
bcex
bellyrub
berniesandlers
bernieslanders
berniestandards
bernlesanders
bettrex
biitrex
biittrex
binan
binanc
binance
binance.com
binanced
binancee
binances
binanse
binnance
bitex
bitfinex
bitfinex.com
bitfinix
bitflip
bithumb
bithumb.com
bitifinex
bitkrx
bitnaru
bitre
bitreex
bitrex
bitrexx
bitrix
bitrrex
bitrtex
bitrx
bitsane
bitsane.com
bitstamp
bitstamp.net
bitt
bitteex
bitter
bitterex
bitterx
bittex
bitthai
bittr
bittrax
bittre
bittrec
bittrecs
bittred
bittreex
bittrek
bittres
bittresx
bittret
bittrev
bittrexchange
bittrex.com
bittrex-deposit
bittrexe
bittrexs
bittrext
bittrexx
bittrexxx
bittrez
bittrix
bittrrex
bittrrx
bittrx
bittrxe
bitttec
bitttex
bitttrex
bittylicious
bittylicious.com
bit-z
blcktrades
blcoktrades
bleutrade
bleutrade.com
blockrade
blockrades
blockrtades
blocktades
blocktardes
blocktraades
blocktrad
blocktrade
blocktraded
blocktradee
blocktradees
blocktrader
blocktraders
block-trades
block-trades-com
blocktrades-com
blocktrades.com
blocktrades-info
blocktrades.info
blocktradess
blocktradesss
blocktrades-us
blocktrades.us
blocktradez
blocktrading
blocktrads
blocktradse
blocktraeds
blocktraes
blocktrdaes
blocktrdes
blocktredes
blockttrades
bloctkrades
bloctrades
blokctrades
bloktrades
bloocktrades
bocktrades
bolcktrades
bomerang
boomeang
boooster
boostar
booste
boosterr
boostr
boostre
boostter
boster
btc38
btcalpha
btc-alpha
btc-alpha.com
btcmarkets
btcmarkets.net
btitrex
btrex
bttrex
bttrx
buildawahle
buildawale
buildawhile
buildwhale
canadiancoconut
ccex
c-cex
c-cex.com
cexio
changellly
changelly.com
changely
coinbas
coinbase
coinbase.com
coinbased
coinegg
coinegg.com
coinpamyents.net
coinpayment
coinpayments
coinpia
coin-room
coinroom.com
coinsmarkets
coinsmarkets.com
coinspot
coinzest
community-coin
coolcoin.com
curi
curied
curies
curing
dcrypto8
decrypto8
deep8
deepcripto8
deepcrpto8
deepcrypo8
deepcryppto8
deepcrypt8
deepcrypto0
deepcrypto7
deepcrypto-8
deepcrypto88
deepcrypto9
deepcryptoo8
deepcryptos
deepcryptos8
deepcryto8
deepcrytpo8
deepcypto8
deeprypto8
depcrypto8
donkeypon
d-tube
eepcrypto8
etherdelta
etherdelta.com
exrates
exx.com
freeewallet
freewalet.org
freewaller
frewallet
fyrstiken
gatecoin.com
gatehub
gatehub.net
gdax.com
gemini.com
good-kama
gtg.witnesses
hitbtc.com
hitbtcexchange
huobi.pro
idex.market
inance
ittrex
ittrexx
kcx
kevinwon
kocostock
koinex
kraken
kraken.com
kucoi
kucoin
kucoinn
kucoins
linkcoin
litebit
little-pepper
livecoin.com
livecoinnet
livingroomofsato
localtrade
localtrade.pro
locktrades
mercatox.com
minnnowbooster
minnobooster
minnooboster
minnoowbooster
minnowboooster
minnowboost
minnowbooste
minnowboosted
minnowboosteer
minnowboosterr
minnowboosters
minnowboostr
minnowboostre
minnowbootser
minnowboster
minnowbuster
minnowhelp
minnowpooster
minnows
minnowsuport
minnowsupports
minnowwbooster
minobooster
minowbooster
minowboster
minowhelper
minowsupport
myupblt
myuupbit
neraex
neraex.com
nextgencrypted
nextgencryptos
okex.com
olonie
oloniex
openledgerdex
paloniex
paypals
pextokens
pfuck
p-funk
piloniex
plolniex
ploniex
plooniex
pokoniex
polaniex
poleniex
poliniex
polionex
pollniex
polloniex
polloniexx
pollonix
polniex
polnoiex
polobiex
poloex
poloiex
poloinex
pololniex
polomiex
polon
poloneex
poloneiex
poloneix
polonex
poloni
poloniax
polonie
poloniec
poloniecs
polonied
poloniee
polonieex
poloniek
polonieks
polonies
poloniet
poloniets
poloniew
poloniexcold
poloniexcom
poloniex.com
poloniexe
poloniexs
poloniext
poloniexwalle
poloniexwallet
poloniexx
poloniexxx
poloniey
poloniez
poloniiex
poloniix
poloniks
poloniox
polonium
polonix
polonixe
polonixx
polonniex
polonoiex
polonox
polonx
polonyex
polooniex
poluniex
pononiex
poolniex
pooloniex
pooniex
poooniex
poponiex
postpromote
postpromotor
prmoobot
pse
ptunk
puloniex
qryptos
qryptos.com
randomwhale
randowale
randowhal
randwhale
rcky1
rendowhale
rockyy1
scoin
shapeshif
shapeshift
steampunks
steemi2t
steemitpay
steempay
steempays
steemti2
steemupbit
stteemit2
sweetsj
sweetssj
sweetsss
sweetsssjs
sweetssssj
swetsssj
tdax
tdax.com
teamsteam
techno-comanche
technocommander
thealien
thebiton
therocktrading
thersing
tidex.com
topbtc
ttrex
upbbit
upbi
upbit
upbit.com
upbits
upbitt
upblt
upm
upmee
uppme
uppmee
viabtc
vittrex
wallet.bitshares
whaleshare
www.aex.com
www.binance.com
www.bitfinex.com
www.bithumb.com
www.bitstamp.net
www.bittrex.com
www.bit-z.com
www.coinbase.com
www.coinegg.com
www.coolcoin.com
www.exx.com
www.gatecoin.com
www.gatehub.net
www.gdax.com
www.huobi.pro
www.kraken.com
www.livecoin.net
www.okex.com
www.poloniex.com
www.qryptos.com
www.xbtce.com
xbtce.com
yobit
yobit.net
youbit
yunbi
zenieix
`
    .trim()
    .split('\n');

export default list;
<commit_msg>update BadActorList<commit_after>const list = `
aalpha
aappreciator
abits
acx
aex.com
alha
alhpa
allcoin.com
alpah
alph
alphha
alppha
alueup
apha
aplha
apppreciator
apprceiator
apprciator
apprecaitor
apprecator
apprecciator
appreciaator
appreciaor
appreciaotr
appreciater
appreciatoor
appreciatorr
appreciatr
appreciatro
appreciattor
appreciiator
apprecitaor
apprecitor
appreeciator
appreiator
appreicator
apprreciator
apreciator
aprpeciator
ausbitban
ausbltbank
avlueup
battrex
bbithumb.hot
bbittrex
bblocktrades
bboomerang
bbooster
bbuildawhale
bcex
bellyrub
berniesandlers
bernieslanders
berniestandards
bernlesanders
bettrex
bihtrex
bihtumb.hot
bihumb.hot
biithumb.hot
biitrex
biittrex
bildawhale
binan
binanc
binance
binance.com
binanced
binancee
binances
binanse
binnance
bit-z
bitex
bitfinex
bitfinex.com
bitfinix
bitflip
bithhumb.hot
bithmb.hot
bithmub.hot
bithub.hot
bithubm.hot
bithum.bhot
bithumb
bithumb-deposit
bithumb-exchange
bithumb-pro
bithumb.com
bithumb.hoot
bithumb.hott
bithumb.hto
bithumb.oht
bithumbb.hot
bithummb.hot
bithuumb.hot
bitifinex
bitkrx
bitnaru
bitre
bitreex
bitrex
bitrexx
bitrix
bitrrex
bitrtex
bitrx
bitsane
bitsane.com
bitstamp
bitstamp.net
bitt
bitteex
bitter
bitterex
bitterx
bittex
bitthai
bittr
bittrax
bittre
bittrec
bittrecs
bittrecx
bittred
bittreex
bittrek
bittres
bittresx
bittret
bittrev
bittrex-deposit
bittrex-pro
bittrex.com
bittrexc
bittrexchange
bittrexe
bittrexs
bittrext
bittrexx
bittrexxx
bittrez
bittrix
bittrrex
bittrrx
bittrx
bittrxe
bitttec
bitttex
bitttrex
bittylicious
bittylicious.com
bituhmb.hot
biuldawhale
blcktrades
blcoktrades
bleutrade
bleutrade.com
bllocktrades
bloccktrades
block-trades
block-trades-com
blockktrades
blockrade
blockrades
blockrtades
blocktades
blocktardes
blocktraades
blocktrad
blocktraddes
blocktrade
blocktraded
blocktradee
blocktradees
blocktrader
blocktraders
blocktrades-com
blocktrades-info
blocktrades-us
blocktrades.com
blocktrades.info
blocktrades.us
blocktradess
blocktradesss
blocktradez
blocktrading
blocktrads
blocktradse
blocktraeds
blocktraes
blocktrdaes
blocktrdes
blocktredes
blocktrrades
blockttrades
bloctkrades
bloctrades
blokctrades
bloktrades
bloocktrades
bocktrades
bolcktrades
bomerang
bomoerang
booemrang
booerang
boomeang
boomearng
boomeerang
boomeraang
boomerag
boomeragn
boomerangg
boomeranng
boomernag
boomerrang
boommerang
boomreang
booomerang
boooster
booser
boosetr
boostar
booste
boosterr
boostr
boostre
boostter
bootser
bosoter
boster
btc-alpha
btc-alpha.com
btc38
btcalpha
btcmarkets
btcmarkets.net
bthumb.hot
btihumb.hot
btitrex
btrex
bttrex
bttrx
buidawhale
buidlawhale
buiildawhale
builadwhale
buildaawhale
buildahale
buildahwale
buildawahle
buildawale
buildawhaale
buildawhael
buildawhalee
buildawhalle
buildawhhale
buildawhile
buildawhlae
buildawwhale
builddawhale
buildwahale
buildwhale
builldawhale
buldawhale
bulidawhale
buobi-pro
buuildawhale
c-cex
c-cex.com
canadiancoconut
ccex
cexio
changellly
changelly.com
changely
cinpayments.net
cionpayments.net
coin-room
coinapyments.net
coinayments.net
coinbas
coinbase
coinbase.com
coinbased
coinegg
coinegg.com
coinpaments.net
coinpamyents.net
coinpayemnts.net
coinpayents.net
coinpaymens.net
coinpaymenst.net
coinpayment
coinpayment.snet
coinpayments
coinpayments.ent
coinpayments.nte
coinpaymetns.net
coinpaymnets.net
coinpaymnts.net
coinpia
coinpyaments.net
coinroom.com
coinsmarkets
coinsmarkets.com
coinspot
coinzest
coipayments.net
coipnayments.net
community-coin
conipayments.net
conpayments.net
coolcoin.com
curi
curied
curies
curing
d-tube
dcrypto8
ddeepcrypto8
decrypto8
deep8
deepccrypto8
deepcripto8
deepcrpto8
deepcrrypto8
deepcrypo8
deepcryppto8
deepcrypt08
deepcrypt8
deepcrypto-8
deepcrypto0
deepcrypto7
deepcrypto88
deepcrypto9
deepcryptoo8
deepcryptos
deepcryptos8
deepcryptto8
deepcryto8
deepcrytpo8
deepcryypto8
deepcypto8
deeppcrypto8
deeprypto8
depcrypto8
donkeypon
edepcrypto8
eepcrypto8
etherdelta
etherdelta.com
exrates
exx.com
feepcrypto8
freeewallet
freewalet.org
freewaller
frewallet
fyrstiken
gatecoin.com
gatehub
gatehub.net
gdax.com
gemini.com
ggopax-deposit
goapx-deposit
goax-deposit
good-kama
goopax-deposit
gopa-deposit
gopa-xdeposit
gopaax-deposit
gopax-ddeposit
gopax-deopsit
gopax-deosit
gopax-depoist
gopax-depoit
gopax-depoosit
gopax-deposiit
gopax-depositt
gopax-depossit
gopax-depost
gopax-deposti
gopax-depposit
gopax-depsit
gopax-depsoit
gopax-dpeosit
gopax-dposit
gopax-edposit
gopax-eposit
gopax-hot
gopaxd-eposit
gopaxx-deposit
goppax-deposit
gopx-deposit
gopxa-deposit
gpax-deposit
gpoax-deposit
gtg.witnesses
herising
hhuobi-pro
hitbtc-deposit
hitbtc-pro
hitbtc.com
hitbtcexchange
hterising
huobbi-pro
huobi-ppro
huobi-pr0
huobi-proo
huobi-prro
huobi.pro
huobii-pro
huobl-pro
huoobi-pro
huuobi-pro
ibthumb.hot
ibttrex
idex.market
imnnowbooster
inance
innowbooster
ithumb.hot
ittrex
ittrexx
kcx
kevinwon
kocostock
koinex
kraken
kraken.com
kucoi
kucoin
kucoinn
kucoins
lapha
lbocktrades
linkcoin
litebit
little-pepper
livecoin.com
livecoinnet
livingroomofsato
localtrade
localtrade.pro
locktrades
lpha
martsteem
mercatox.com
miinnowbooster
minnnowbooster
minnobooster
minnobwooster
minnooboster
minnoowbooster
minnowboooster
minnowbooser
minnowboosetr
minnowboosster
minnowboost
minnowbooste
minnowboosted
minnowboosteer
minnowboosterr
minnowboosters
minnowboostr
minnowboostre
minnowboostter
minnowbootser
minnowbosoter
minnowboster
minnowbuster
minnowhelp
minnowoboster
minnowooster
minnowpooster
minnows
minnowsuport
minnowsupports
minnowwbooster
minnwbooster
minnwobooster
minobooster
minonwbooster
minowbooster
minowboster
minowhelper
minowsupport
mminnowbooster
mmyupbit
mninowbooster
msartsteem
my-upbit
myupbbit
myupbiit
myupbitt
myupblt
myuppbit
myuupbit
myyupbit
neraex
neraex.com
nextgencrypted
nextgencryptos
obomerang
oboster
ocky1
oenledger-dex
oepnledger-dex
ogpax-deposit
oinpayments.net
okex.com
olonie
oloniex
oomerang
oopenledger-dex
ooster
opeenledger-dex
opeledger-dex
opelnedger-dex
openedger-dex
openeldger-dex
openldeger-dex
openldger-dex
openleddger-dex
openledegr-dex
openleder-dex
openledge-dex
openledge-rdex
openledgeer-dex
openledger-ddex
openledger-de
openledger-deex
openledger-dx
openledger-dxe
openledger-edx
openledger-ex
openledger-pro
openledgerd-ex
openledgerdex
openledgerr-dex
openledgr-dex
openledgre-dex
openleedger-dex
openlegder-dex
openleger-dex
openlledger-dex
opennledger-dex
opnledger-dex
oppenledger-dex
opstpromoter
orcky1
ostpromoter
p-funk
paloniex
papreciator
paypals
penledger-dex
pextokens
pfuck
piloniex
plolniex
ploniex
plooniex
poenledger-dex
pokoniex
polaniex
poleniex
poliniex
polionex
pollniex
polloniex
polloniexx
pollonix
polniex
polnoiex
polobiex
poloex
poloiex
poloinex
pololniex
polomiex
polon
poloneex
poloneiex
poloneix
polonex
poloni
poloniax
polonie
poloniec
poloniecs
polonied
poloniee
polonieex
poloniek
polonieks
polonies
poloniet
poloniets
poloniew
poloniex.com
poloniexcold
poloniexcom
poloniexe
poloniexs
poloniext
poloniexwalle
poloniexwallet
poloniexx
poloniexxx
poloniey
poloniez
poloniiex
poloniix
poloniks
poloniox
polonium
polonix
polonixe
polonixx
polonniex
polonoiex
polonox
polonx
polonyex
polooniex
poluniex
pomobot
pononiex
poolniex
pooloniex
pooniex
poooniex
poostpromoter
poponiex
pormobot
posptromoter
posstpromoter
postpormoter
postppromoter
postprmooter
postprmoter
postprommoter
postpromoer
postpromooter
postpromote
postpromoteer
postpromoterr
postpromotor
postpromotre
postpromotter
postpromter
postpromtoer
postproomoter
postproomter
postprooter
postprromoter
postromoter
posttpromoter
potpromoter
potspromoter
ppostpromoter
ppreciator
ppromobot
prmobot
prmoobot
promboot
prombot
prommobot
promobbot
promobo
promoboot
promobott
promobt
promobto
promoobot
promoobt
promoot
proobot
proombot
proomobot
prromobot
pse
psotpromoter
pstpromoter
ptakundamianshow
ptunk
puloniex
qryptos
qryptos.com
randomwhale
randowale
randowhal
randwhale
rcky1
rcoky1
rdex
rduex
rendowhale
roccky1
rock1y
rockky1
rockyy1
rocy1
rocyk1
rokcy1
romobot
roocky1
rpomobot
rrocky1
rrudex
ruddex
rudeex
rudexx
rudx
rudxe
ruedx
ruudex
samrtsteem
sartsteem
scoin
seem
seemit
seemit2
seepcrypto8
setem
setemit
setemit2
shapeshif
shapeshift
smaartsteem
smarrtsteem
smarstteem
smartseem
smartsetem
smartstee
smartsteeem
smartsteemm
smartsteme
smartstteem
smartteem
smatrsteem
smmartsteem
smratsteem
smrtsteem
ssmartsteem
ssteemit2
steampunks
steeemit2
steeimt
steeimt2
steeit
steeit2
steemi2
steemi2t
steemitpay
steemitt2
steemmit2
steempay
steempays
steemt2
steemti2
steemupbit
stemeit
stemeit2
stemit1
stemit2
stemit3
stemit4
stteem
stteemit2
sweetsj
sweetssj
sweetsss
sweetsssjs
sweetssssj
swetsssj
tdax
tdax.com
teamsteam
techno-comanche
technocommander
teemit2
tehrising
terising
thealien
thebiton
theerising
theirsing
theising
theriing
theriising
theriisng
therisig
therisign
therisiing
therisingg
therisinng
therisng
therisnig
therissing
therocktrading
therrising
thersiing
thersing
thherising
threising
thrising
tidex.com
topbtc
tseem
tseemit
tseemit2
ttherising
ttrex
ubildawhale
udex
uhobi-pro
uildawhale
umewhale
umpewhale
uobi-pro
upbbit
upbi
upbit
upbit.com
upbits
upbitt
upblt
upemwhale
upewhale
upm
upmee
upmeewhale
upmehale
upmehwale
upmewahle
upmewhaale
upmewhae
upmewhael
upmewhalee
upmewhalle
upmewhhale
upmewhlae
upmewhle
upmewwhale
upmme
upmmewhale
upmwehale
upmwhale
uppme
uppmee
uppmewhale
uupmewhale
vaalueup
valeup
valeuup
vallueup
valueeup
valuep
valuepu
valueu
valueupp
valuuep
valuueup
valuup
vaueup
vauleup
viabtc
vittrex
vlaueup
vlueup
vvalueup
wallet.bitshares
whaleshare
www.aex.com
www.binance.com
www.bit-z.com
www.bitfinex.com
www.bithumb.com
www.bitstamp.net
www.bittrex.com
www.coinbase.com
www.coinegg.com
www.coolcoin.com
www.exx.com
www.gatecoin.com
www.gatehub.net
www.gdax.com
www.huobi.pro
www.kraken.com
www.livecoin.net
www.okex.com
www.poloniex.com
www.qryptos.com
www.xbtce.com
xbtce.com
ymupbit
yobit
yobit.net
youbit
yunbi
zenieix
`
    .trim()
    .split('\n');

export default list;
<|endoftext|>


<commit_before>"use strict";

Tlgr.tlgrVersion = "1";
Tlgr.gjpVersion = "1";
Tlgr.inviteIdLength = 128;
Tlgr.groupUidLength = 128;
Tlgr.channelIdLength = 32;
Tlgr.sharedKeyLength = 256;
Tlgr.keyPairLength = 512;
Tlgr.hashCount = 1000;
Tlgr.hashLength = 128;
Tlgr.ivLength = 128;
Tlgr.keyLength = 128;
Tlgr.messageTypes = {
    "REKEY_INFO": "rekey info",
    "CHANNEL_ABANDONED": "channel abandoned",
    "TEXT" : "text",
    "GJP" : "gjp"
}

var forge = require("forge");
var rsa = require("../modules/cryptography/rsa-forge");
var AES = require("../modules/cryptography/aes-forge");
var SHA1 = require("../modules/cryptography/sha1-crypto-js");

var eventEmitter = require("../modules/events/eventEmitter");
var invariant = require("../modules/invariant");

var Multivalue = require("../modules/multivalue/multivalue");
var Hex = require("../modules/multivalue/hex");
var Utf8String = require("../modules/multivalue/utf8string");
var ByteBuffer = require("../modules/multivalue/byteBuffer");
var BitArray = require("../modules/multivalue/bitArray");

var serializable = require("../modules/serialization/serializable");
var urandom = require("../modules/urandom/urandom");

var tools = require("../modules/tools");
var extend = tools.extend;
var isFunction = tools.isFunction;

// __________________________________________________________________________ //

function SerializationHelper() {

}

SerializationHelper.serializeValueAsHex = function (value) {
    return value ? value.as(Hex).serialize() : null;
}

SerializationHelper.serializeValue = function (value) {
    return value ? value.serialize() : null;
}

SerializationHelper.deserializeValueAsHex = function (value) {
    return value ? Hex.deserialize(value) : null;
}

// __________________________________________________________________________ //

function Users() {
    this._byAid = {};
}

Users.prototype.getUsers = function () {
    return Object.keys(this._byAid).map(function (item) {
        return {
            aid: item,
            name: this._byAid[item].meta.name
        }
    }, this);
};

Users.prototype.getUserData = function (aid) {
    if (aid instanceof Multivalue) {
        return this.getUserData(aid.as(Hex).serialize());
    }
    if (typeof aid === 'string' || aid instanceof String) {
        return this._byAid[aid];
    }
}

Users.prototype.putUserData = function (data) {
    this._byAid[data.aid.as(Hex).serialize()] = data;
}

Users.prototype.removeUserData = function (data) {
    delete this._byAid[data.aid.as(Hex).serialize()];
}

Users.prototype.findUserByHash = function (hx) {
    var hex = hx.as(Hex);
    for (var index in this._byAid) {
        var user = this._byAid[index];
        if (user.ht.as(Hex).isEqualTo(hex)) {
            return user;
        }
    }
}

Users.prototype.serialize = function () {
    var byAid = this._byAid;
    var result = {};
    for (var key in byAid) {
        result[key] = {
            aid: byAid[key].aid.as(Hex).serialize(),
            ht: byAid[key].ht.as(Hex).serialize(),
            publicKey: byAid[key].publicKey.serialize(),
            meta: byAid[key].meta
        }
    }
    return result;
}

Users.prototype.deserialize = function (byAid) {
    for (var key in byAid) {
        this._byAid[key] = {
            aid: Hex.deserialize(byAid[key].aid),
            ht: Hex.deserialize(byAid[key].ht),
            meta: byAid[key].meta,
            publicKey: rsa.PublicKey.deserialize(byAid[key].publicKey)
        }
    }
}

// __________________________________________________________________________ //

function Algo(random) {
    this._random = random;

    this._groupUID = null;
    this._channelID = null;
    this._sharedKey = null;
    this._inviteId = null;
    this._hashStart = null;
    this._hashTail = null;
    this._users = new Users();

    this._keyPair = rsa.generateKeyPair({bits: Tlgr.keyPairLength});
    this._aid = rsa.getPublicKeyFingerprint(this._keyPair.publicKey);
};

Algo.prototype.getUID = function () {
    return this._groupUid.as(Hex).serialize();
};

Algo.prototype.getUsers = function () {
    return this._users;
};

Algo.prototype.getChannelId = function () {
    return this._channelId;
}

Algo.prototype.getAid = function () {
    return this._aid;
}

Algo.prototype.getMyAid = function () {
    return this._aid.as(Hex).toString();
}

Algo.prototype.getMyName = function () {
    return this._users.getUserData(this.getMyAid()).meta.name;
}

Algo.prototype._hash = function (value) {
    return SHA1(value).as(BitArray).bitSlice(0, Tlgr.hashLength);
};

Algo.prototype._getRandomBytes = function (bitLength) {
    invariant(this._random, "random was not set");
    invariant(isFunction(this._random.bitArray), "random must implement IRandom");
    return this._random.bitArray(bitLength);
};

Algo.prototype._nextHashTail = function() {
    var current = this._hashStart;
    for (var i = 0; i < Tlgr.hashCount; i += 1) {
        var next = this._hash(current);
        if(next.as(Hex).isEqualTo(this._hashTail.as(Hex))) {
            this._hashTail = current;
            return next;
        }
        current = next;
    }
};

Algo.prototype.createChannel = function() {
    this._groupUid = this._getRandomBytes(Tlgr.groupUidLength);
    this._channelId = this._getRandomBytes(Tlgr.channelIdLength);
    this._sharedKey = this._getRandomBytes(Tlgr.sharedKeyLength);
};

Algo.prototype.generateInvite = function () {
    var inviteId = this._getRandomBytes(Tlgr.inviteIdLength);

    return {
        "pVer": Tlgr.tlgrVersion,
        "inviteId": inviteId.as(Hex).serialize(),
        "groupUid": this._groupUid.as(Hex).serialize(),
        "channelId": this._channelId.as(Hex).serialize(),
        "sharedKey": this._sharedKey.as(Hex).serialize(),
    };
};

Algo.prototype.acceptInvite = function (invite) {
    invariant(invite.pVer == Tlgr.tlgrVersion, "invalid protocol version");
    this._inviteId = Hex.deserialize(invite.inviteId);
    this._groupUid = Hex.deserialize(invite.groupUid);
    this._channelId = Hex.deserialize(invite.channelId);
    this._sharedKey = Hex.deserialize(invite.sharedKey);
};

Algo.prototype.generateGroupJoinPackage = function (metadata) {
    this._hashStart = this._getRandomBytes(Tlgr.hashLength);
    this._hashTail = this._hashStart;
    for (var i = 0; i < Tlgr.hashCount; i += 1) {
        this._hashTail = this._hash(this._hashTail);
    }

    var gjp = {
        "ver": [Tlgr.tlgrVersion, Tlgr.gjpVersion],
        "ht": this._hashTail.as(Hex).serialize(),
        "meta": (metadata)?(metadata):({}),
        "pk": this._keyPair.publicKey.serialize(),
        "aid": this._aid.as(Hex).serialize(),
    };
    if (this._inviteId) {
        gjp.invite = this._inviteId.as(Hex).serialize();
    }

    var values = [gjp.ver, gjp.aid, gjp.ht, gjp.meta, gjp.pk];
    var sign = this._keyPair.privateKey.sign(JSON.stringify(values));
    gjp.sign = sign.as(Hex).serialize();
    return gjp;
};

Algo.prototype.looksLikeGJP = function (gjp) {
    if(typeof gjp === "object") {
        return gjp.aid && gjp.pk && gjp.meta && gjp.ht && gjp.ver && gjp.sign;
    } else {
        return false;
    }
};

Algo.prototype.processGroupJoinPackage = function (gjp) {
    var publicKey = rsa.PublicKey.deserialize(gjp.pk);
    var aid = Hex.deserialize(gjp.aid);
    var values = [gjp.ver, gjp.aid, gjp.ht, gjp.meta, gjp.pk];
    if (!publicKey.verify(JSON.stringify(values), Hex.deserialize(gjp.sign))) {
        // invalid signature
        return;
    }
    var ht = Hex.deserialize(gjp.ht);
    var data = {
        "aid": aid,
        "publicKey": publicKey,
        "meta": gjp.meta,
        "ht": ht,
    };
    this._users.putUserData(data)
    return data;
};

Algo.prototype.privatize = function (aid, data) {
    var key = this._getRandomBytes(Tlgr.keyLength);
    var iv = this._getRandomBytes(Tlgr.ivLength);

    var user = this._users.getUserData(aid);
    var encrypted = AES.encryptCbc(data, key, iv);
    var encrypted_key = user.publicKey.encrypt(key, 'RSA-OAEP');

    return encrypted_key.as(ByteBuffer).concat(iv).concat(encrypted);
};

Algo.prototype.deprivatize = function(message) {
    var encrypted = message.as(ByteBuffer);
    var encrypted_key = encrypted.take(Tlgr.keyPairLength);
    var iv = encrypted.take(Tlgr.ivLength);
    var key = this._keyPair.privateKey.decrypt(encrypted_key, 'RSA-OAEP');

    return AES.decryptCbc(encrypted, key, iv);
};

Algo.prototype.encrypt = function (message) {
    invariant(this._sharedKey, "not configured");
    var hx = this._nextHashTail();
    var data = hx.as(ByteBuffer).concat(message);
    var iv = this._getRandomBytes(Tlgr.ivLength);
    var encrypted = AES.encryptCbc(data, this._sharedKey, iv);
    return iv.as(ByteBuffer).concat(encrypted);
};

Algo.prototype.decrypt = function (message) {
    invariant(this._sharedKey, "not configured");
    var encrypted = message.as(ByteBuffer);
    var iv = encrypted.take(Tlgr.ivLength);
    var data = AES.decryptCbc(encrypted, this._sharedKey, iv);

    var message = data.as(ByteBuffer);
    var hx = message.take(Tlgr.hashLength);

    // find message owner
    for (var i = 0; i < Tlgr.hashCount; i += 1) {
        var user = this._users.findUserByHash(hx);
        if(user) {
            return {
                "sender": user,
                "message": message,
            }
        }
        hx = this._hash(hx);
    }
    return {
        "message": message,
    }
};

Algo.prototype.serialize = function () {
    return {
        groupUid: SerializationHelper.serializeValueAsHex(this._groupUid),
        channelId: SerializationHelper.serializeValueAsHex(this._channelId),
        sharedKey: SerializationHelper.serializeValueAsHex(this._sharedKey),
        inviteId: SerializationHelper.serializeValueAsHex(this._inviteId),
        hashStart: SerializationHelper.serializeValueAsHex(this._hashStart),
        hashTail: SerializationHelper.serializeValueAsHex(this._hashTail),
        publicKey: SerializationHelper.serializeValue(this._keyPair.publicKey),
        privateKey: SerializationHelper.serializeValue(this._keyPair.privateKey),
        users: this._users.serialize(),
        aid: SerializationHelper.serializeValueAsHex(this._aid)
    };
}

Algo.prototype.deserialize = function (data) {
    this._keyPair = { };
    this._keyPair.publicKey = (data.publicKey)?(rsa.PublicKey.deserialize(data.publicKey)):null;
    this._keyPair.privateKey = (data.privateKey)?(rsa.PrivateKey.deserialize(data.privateKey)):null;
    this._groupUid = SerializationHelper.deserializeValueAsHex(data.groupUid);
    this._channelId = SerializationHelper.deserializeValueAsHex(data.channelId);
    this._sharedKey = SerializationHelper.deserializeValueAsHex(data.sharedKey);
    this._inviteId = SerializationHelper.deserializeValueAsHex(data.inviteId);
    this._hashStart = SerializationHelper.deserializeValueAsHex(data.hashStart);
    this._hashTail = SerializationHelper.deserializeValueAsHex(data.hashTail);
    if(data.users) {
        this._users.deserialize(data.users);
    }
    this._aid = SerializationHelper.deserializeValueAsHex(data.aid);
}

Tlgr.Algo = Algo;
// __________________________________________________________________________ //

function Tlgr(factory) {
    console.log("Constructing Tlgr...");
    invariant(factory, "Can be constructed only with factory");
    invariant(isFunction(factory.createRandom), "factory must have createRandom() method");

    this._defineEvent("changed");
    this._defineEvent("packet");
    this._defineEvent("openAddrIn");
    this._defineEvent("closeAddrIn");
    this._defineEvent("message");
    this._defineEvent("user_joined");
    this._defineEvent("rekey");
    this._defineEvent("user_left");

    this._factory = factory;
    this._random = factory.createRandom();
    this._algo = new Algo(this._random);
}

extend(Tlgr.prototype, eventEmitter, serializable, {
    serialize: function (packet, context) {
        var data = this._algo.serialize();
        packet.setData(data);
    },

    deserialize: function (packet, context) {
        var data = packet.getData();
        this._algo.deserialize(data);
    },

    getUID: function () {
        return this._algo.getUID();
    },

    getUsers: function () {
        return this._algo.getUsers().getUsers();
    },

    makePrivateMessage: function (aid, message/*string*/) {
        var usrData = this._algo.getUsers().getUserData(aid);
        var encrypted = this._algo.privatize(Hex.deserialize(aid), new Utf8String(message));
        var msg = {
            type: Tlgr.messageTypes.REKEY_INFO,
            data: encrypted.as(Hex).serialize()
        }
        return msg;
    },

    //rekeyInfo -  invitation object
    sendRekeyInfo: function (aidList, rekeyInfo) {
        aidList.forEach(function (aid) {
            var usrData = this._algo.getUsers().getUserData(aid);
            if (usrData) {
                var msg = this.makePrivateMessage(aid, JSON.stringify(rekeyInfo));
                this.fire("packet", {
                    addr: this._algo.getChannelId(),
                    data: this._algo.encrypt(new Utf8String(JSON.stringify(msg)))
                });
            }
        }, this);
        this.fire("changed", this);
    },

    sendChannelAbandoned: function (reasonRekey) {
        var msg = {
            type: "channel abandoned",
            data: (reasonRekey)?("reason=rekey"):("reason=user exit")
        }
        this.fire("packet", {
            addr: this._algo.getChannelId(),
            data: this._algo.encrypt(new Utf8String(JSON.stringify(msg)))
        });
        this.fire("changed", this);
    },

    afterDeserialize: function () {
        this._channelContext = urandom.int(0, 0xFFFFFFFF);
        this.fire("openAddrIn", {
            addr: this._algo.getChannelId(),
            context: this._channelContext,
            fetch: false
        });
    },

    getMyAid: function () {
        return this._algo.getMyAid();
    },

    getMyName: function () {
        return this._algo.getMyName();
    },

    //process only packets from our  channel
    onNetworkPacket: function (networkPacket) {
        invariant(networkPacket
            && networkPacket.addr instanceof Multivalue
            && networkPacket.data instanceof Multivalue, "networkPacket must be {addr: multivalue, data: multivalue}");
        if (this._algo.getChannelId() && this._algo.getChannelId().as(Hex).isEqualTo(networkPacket.addr.as(Hex))) {
            //packet is for our channel lets try to decrypt
            console.log("Tlgr: trying to decrypt packet");
            var message = null;
            var decryptedData = null;
            try {
                decryptedData = this._algo.decrypt(networkPacket.data);
                message = JSON.parse(decryptedData.message.as(Utf8String).toString());
            }catch (e)
            {
                console.log(e);
                return;
            }

            if(decryptedData.sender) {
                console.log("Tlgr got something: ", decryptedData.sender, message);
                //if not our own text msg
                if(decryptedData.sender.aid.as(Hex).toString() !== this._algo.getAid().as(Hex).toString() &&
                        message.type === Tlgr.messageTypes.TEXT) {
                    this.fire("message", {
                        sender: {
                            aid: decryptedData.sender.aid.as(Hex).toString(),
                            name: decryptedData.sender.meta.name
                        },
                        text: message.data
                    });
                    // == CHANNEL_ABANDONED
                } else if (message.type === Tlgr.messageTypes.CHANNEL_ABANDONED) {
                    if (message.data === "reason=user exit") {
                        this._algo.getUsers().removeUserData(decryptedData.sender);
                        this.fire("user_left", {
                            aid: decryptedData.sender.aid.as(Hex).toString(),
                            name: decryptedData.sender.meta.name
                        });
                    }
                } else if (message.type === Tlgr.messageTypes.REKEY_INFO) {
                    try {
                        var encrypted = Hex.deserialize(message.data);
                        var decrypted = this._algo.deprivatize(encrypted);
                        console.log("Tlgr decrypted private message: ", decrypted);
                        decrypted = JSON.parse(decrypted.as(Utf8String).toString());

                        this.fire("rekey", decrypted);
                        this.fire("changed", this);
                        return;
                    } catch (e) {
                    }
                }
            }else if(message.type === Tlgr.messageTypes.GJP && this._algo.looksLikeGJP(message.data)) {
                console.log("Tlgr got gjp", message.data);
                var userData = this._algo.processGroupJoinPackage(message.data);
                if(userData) {
                    this.fire("user_joined", {
                            aid: userData.aid.as(Hex).toString(),
                            name: userData.meta.name
                        });
                }
            }
            this.fire("changed", this);
        }
    },

    generateInvitation: function () {
        return this._algo.generateInvite();
    },

    sendMessage: function (text) {
        invariant(typeof text === "string", "tlgr.sendMessage text must be string");
        var msg = {
            type: Tlgr.messageTypes.TEXT,
            data: text
        }
        this.fire("packet", {
            addr: this._algo.getChannelId(),
            data: this._algo.encrypt(new Utf8String(JSON.stringify(msg)))
        });
        this.fire("changed", this);
    },

    //if args has invite we accept it, if not - we create new channel
    init: function (args) {
        invariant(this._random, "rng is not set");
        this.checkEventHandlers();
        if(args.invite){
            this._algo.acceptInvite(args.invite);
        }else {
            this._algo.createChannel();
        }
        this._channelContext = urandom.int(0, 0xFFFFFFFF);
        //lets listen for packets from that channel
        this.fire("openAddrIn", {
            addr: this._algo.getChannelId(),
            context: this._channelContext,
            fetch: true
        });
        //send group join package
        var gjp = this._algo.generateGroupJoinPackage({name:args.userName});
        gjp = {
            type: Tlgr.messageTypes.GJP,
            data: gjp
        };
        var gjpJson = JSON.stringify(gjp);

        this.fire("packet", {
            addr: this._algo.getChannelId(),
            data: this._algo.encrypt(new Utf8String(gjpJson))
        });
    },

});

module.exports = Tlgr;
<commit_msg>cleaned tlgr algo<commit_after>"use strict";

TlgrAlgo.tlgrVersion = "1";
TlgrAlgo.gjpVersion = "1";
TlgrAlgo.inviteIdLength = 128;
TlgrAlgo.groupUidLength = 128;
TlgrAlgo.channelIdLength = 32;
TlgrAlgo.sharedKeyLength = 256;
TlgrAlgo.keyPairLength = 512;
TlgrAlgo.hashCount = 1000;
TlgrAlgo.hashLength = 128;
TlgrAlgo.ivLength = 128;
TlgrAlgo.keyLength = 128;
TlgrAlgo.messageTypes = {
    "REKEY_INFO": "rekey info",
    "CHANNEL_ABANDONED": "channel abandoned",
    "TEXT" : "text",
    "GJP" : "gjp"
}

var rsa = require("../modules/cryptography/rsa-forge");
var AES = require("../modules/cryptography/aes-forge");
var SHA1 = require("../modules/cryptography/sha1-crypto-js");

var invariant = require("../modules/invariant");

var Hex = require("../modules/multivalue/hex");
var Utf8String = require("../modules/multivalue/utf8string");
var ByteBuffer = require("../modules/multivalue/byteBuffer");
var BitArray = require("../modules/multivalue/bitArray");

var tools = require("../modules/tools");
var isFunction = tools.isFunction;

var Users = require('./users');

function TlgrAlgo(random) {
    this._random = random;

    this._groupUID = null;
    this._channelID = null;
    this._sharedKey = null;
    this._inviteId = null;
    this._hashStart = null;
    this._hashTail = null;
    this._users = new Users();

    this._keyPair = rsa.generateKeyPair({bits: TlgrAlgo.keyPairLength});
    this._aid = rsa.getPublicKeyFingerprint(this._keyPair.publicKey);
};

TlgrAlgo.prototype.getUID = function () {
    return this._groupUid.as(Hex).serialize();
};

TlgrAlgo.prototype.getUsers = function () {
    return this._users;
};

TlgrAlgo.prototype.getChannelId = function () {
    return this._channelId;
}

TlgrAlgo.prototype.getAid = function () {
    return this._aid;
}

TlgrAlgo.prototype.getMyAid = function () {
    return this._aid.as(Hex).toString();
}

TlgrAlgo.prototype.getMyName = function () {
    return this._users.getUserData(this.getMyAid()).meta.name;
}

TlgrAlgo.prototype._hash = function (value) {
    return SHA1(value).as(BitArray).bitSlice(0, TlgrAlgo.hashLength);
};

TlgrAlgo.prototype._getRandomBytes = function (bitLength) {
    invariant(this._random, "random was not set");
    invariant(isFunction(this._random.bitArray), "random must implement IRandom");
    return this._random.bitArray(bitLength);
};

TlgrAlgo.prototype._nextHashTail = function() {
    var current = this._hashStart;
    for (var i = 0; i < TlgrAlgo.hashCount; i += 1) {
        var next = this._hash(current);
        if(next.as(Hex).isEqualTo(this._hashTail.as(Hex))) {
            this._hashTail = current;
            return next;
        }
        current = next;
    }
};

TlgrAlgo.prototype.createChannel = function() {
    this._groupUid = this._getRandomBytes(TlgrAlgo.groupUidLength);
    this._channelId = this._getRandomBytes(TlgrAlgo.channelIdLength);
    this._sharedKey = this._getRandomBytes(TlgrAlgo.sharedKeyLength);
};

TlgrAlgo.prototype.generateInvite = function () {
    var inviteId = this._getRandomBytes(TlgrAlgo.inviteIdLength);

    return {
        "pVer": TlgrAlgo.tlgrVersion,
        "inviteId": inviteId.as(Hex).serialize(),
        "groupUid": this._groupUid.as(Hex).serialize(),
        "channelId": this._channelId.as(Hex).serialize(),
        "sharedKey": this._sharedKey.as(Hex).serialize(),
    };
};

TlgrAlgo.prototype.acceptInvite = function (invite) {
    invariant(invite.pVer == TlgrAlgo.tlgrVersion, "invalid protocol version");
    this._inviteId = Hex.deserialize(invite.inviteId);
    this._groupUid = Hex.deserialize(invite.groupUid);
    this._channelId = Hex.deserialize(invite.channelId);
    this._sharedKey = Hex.deserialize(invite.sharedKey);
};

TlgrAlgo.prototype.generateGroupJoinPackage = function (metadata) {
    this._hashStart = this._getRandomBytes(TlgrAlgo.hashLength);
    this._hashTail = this._hashStart;
    for (var i = 0; i < TlgrAlgo.hashCount; i += 1) {
        this._hashTail = this._hash(this._hashTail);
    }

    var gjp = {
        "ver": [TlgrAlgo.tlgrVersion, TlgrAlgo.gjpVersion],
        "ht": this._hashTail.as(Hex).serialize(),
        "meta": (metadata)?(metadata):({}),
        "pk": this._keyPair.publicKey.serialize(),
        "aid": this._aid.as(Hex).serialize(),
    };
    if (this._inviteId) {
        gjp.invite = this._inviteId.as(Hex).serialize();
    }

    var values = [gjp.ver, gjp.aid, gjp.ht, gjp.meta, gjp.pk];
    var sign = this._keyPair.privateKey.sign(JSON.stringify(values));
    gjp.sign = sign.as(Hex).serialize();
    return gjp;
};

TlgrAlgo.prototype.looksLikeGJP = function (gjp) {
    if(typeof gjp === "object") {
        return gjp.aid && gjp.pk && gjp.meta && gjp.ht && gjp.ver && gjp.sign;
    } else {
        return false;
    }
};

TlgrAlgo.prototype.processGroupJoinPackage = function (gjp) {
    var publicKey = rsa.PublicKey.deserialize(gjp.pk);
    var aid = Hex.deserialize(gjp.aid);
    var values = [gjp.ver, gjp.aid, gjp.ht, gjp.meta, gjp.pk];
    if (!publicKey.verify(JSON.stringify(values), Hex.deserialize(gjp.sign))) {
        // invalid signature
        return;
    }
    var ht = Hex.deserialize(gjp.ht);
    var data = {
        "aid": aid,
        "publicKey": publicKey,
        "meta": gjp.meta,
        "ht": ht,
    };
    this._users.putUserData(data)
    return data;
};

TlgrAlgo.prototype.privatize = function (aid, data) {
    var key = this._getRandomBytes(TlgrAlgo.keyLength);
    var iv = this._getRandomBytes(TlgrAlgo.ivLength);

    var user = this._users.getUserData(aid);
    var encrypted = AES.encryptCbc(data, key, iv);
    var encrypted_key = user.publicKey.encrypt(key, 'RSA-OAEP');

    return encrypted_key.as(ByteBuffer).concat(iv).concat(encrypted);
};

TlgrAlgo.prototype.deprivatize = function(message) {
    var encrypted = message.as(ByteBuffer);
    var encrypted_key = encrypted.take(TlgrAlgo.keyPairLength);
    var iv = encrypted.take(TlgrAlgo.ivLength);
    var key = this._keyPair.privateKey.decrypt(encrypted_key, 'RSA-OAEP');

    return AES.decryptCbc(encrypted, key, iv);
};

TlgrAlgo.prototype.encrypt = function (message) {
    invariant(this._sharedKey, "not configured");
    var hx = this._nextHashTail();
    var data = hx.as(ByteBuffer).concat(message);
    var iv = this._getRandomBytes(TlgrAlgo.ivLength);
    var encrypted = AES.encryptCbc(data, this._sharedKey, iv);
    return iv.as(ByteBuffer).concat(encrypted);
};

TlgrAlgo.prototype.decrypt = function (message) {
    invariant(this._sharedKey, "not configured");
    var encrypted = message.as(ByteBuffer);
    var iv = encrypted.take(TlgrAlgo.ivLength);
    var data = AES.decryptCbc(encrypted, this._sharedKey, iv);

    var message = data.as(ByteBuffer);
    var hx = message.take(TlgrAlgo.hashLength);

    // find message owner
    for (var i = 0; i < TlgrAlgo.hashCount; i += 1) {
        var user = this._users.findUserByHash(hx);
        if(user) {
            return {
                "sender": user,
                "message": message,
            }
        }
        hx = this._hash(hx);
    }
    return {
        "message": message,
    }
};

TlgrAlgo.prototype.serialize = function () {
    return {
        groupUid: SerializationHelper.serializeValueAsHex(this._groupUid),
        channelId: SerializationHelper.serializeValueAsHex(this._channelId),
        sharedKey: SerializationHelper.serializeValueAsHex(this._sharedKey),
        inviteId: SerializationHelper.serializeValueAsHex(this._inviteId),
        hashStart: SerializationHelper.serializeValueAsHex(this._hashStart),
        hashTail: SerializationHelper.serializeValueAsHex(this._hashTail),
        publicKey: SerializationHelper.serializeValue(this._keyPair.publicKey),
        privateKey: SerializationHelper.serializeValue(this._keyPair.privateKey),
        users: this._users.serialize(),
        aid: SerializationHelper.serializeValueAsHex(this._aid)
    };
}

TlgrAlgo.prototype.deserialize = function (data) {
    this._keyPair = { };
    this._keyPair.publicKey = (data.publicKey)?(rsa.PublicKey.deserialize(data.publicKey)):null;
    this._keyPair.privateKey = (data.privateKey)?(rsa.PrivateKey.deserialize(data.privateKey)):null;
    this._groupUid = SerializationHelper.deserializeValueAsHex(data.groupUid);
    this._channelId = SerializationHelper.deserializeValueAsHex(data.channelId);
    this._sharedKey = SerializationHelper.deserializeValueAsHex(data.sharedKey);
    this._inviteId = SerializationHelper.deserializeValueAsHex(data.inviteId);
    this._hashStart = SerializationHelper.deserializeValueAsHex(data.hashStart);
    this._hashTail = SerializationHelper.deserializeValueAsHex(data.hashTail);
    if(data.users) {
        this._users.deserialize(data.users);
    }
    this._aid = SerializationHelper.deserializeValueAsHex(data.aid);
}

module.exports = TlgrAlgo;
<|endoftext|>