<commit_before>//- JavaScript source code

//- defs-postgres.js ~~
//
//  These definitions assume Postgres 9.0 or later. They also need optimization
//  help from an RDBMS guru.
//
//  Known shortcomings:
//  -   The log storage definition assumes that hstore is available.
//
//                                                      ~~ (c) SRW, 25 Sep 2012
//                                                  ~~ last updated 31 Jan 2015

(function () {
    'use strict';

 // Pragmas

    /*jshint maxparams: 3, quotmark: single, strict: true */

    /*jslint indent: 4, maxlen: 80, node: true */

    /*properties
        api, avar_ttl, body, collect_garbage, connect, error, get_avar,
        get_list, hasOwnProperty, isMaster, isWorker, join, key, length, log,
        map, native, persistent_storage, postgres, push, query, rows, set_avar,
        stringify, trafficlog_storage
    */

 // Declarations

    var cluster, pg;

 // Definitions

    cluster = require('cluster');

    try {
     // If the "pg-native" module is installed, use it for a 30% boost in
     // performance. QM lists "pg-native" as an optional dependency.
        pg = require('pg').native;
    } catch (err) {
     // Fall back to the JS (non-native) implementation of the module :-)
        pg = require('pg');
    }

 // Out-of-scope definitions

    exports.api = function (settings) {
     // This function needs documentation.

        var collect_garbage, connection_string, get_avar, get_list,
            set_avar;

        collect_garbage = function () {
         // This function is only a placeholder, now that QM uses an INSERT
         // trigger to evict old rows automatically.
            return;
        };

        connection_string = settings.persistent_storage.postgres;

        get_avar = function (params, callback) {
         // This function needs documentation.
            pg.connect(connection_string, function (err, client, done) {
             // This function needs documentation.
                if (err !== null) {
                    done();
                    return callback(err, '{}');
                }
                var x = [
                    'UPDATE avars SET last_touch = NOW()',
                    'WHERE box = $1 AND key = $2 AND ' +
                        'last_touch > NOW() - INTERVAL \'' +
                        settings.avar_ttl + ' seconds\'',
                    'RETURNING body'
                ].join(' ');
                client.query(x, params, function (err, results) {
                 // This function needs documentation.
                    done();
                    if (err !== null) {
                        return callback(err, '{}');
                    }
                    if (results.rows.length === 0) {
                        return callback(null, '{}');
                    }
                    return callback(null, results.rows[0].body);
                });
                return;
            });
            return;
        };

        get_list = function (params, callback) {
         // This function needs documentation.
            pg.connect(connection_string, function (err, client, done) {
             // This function needs documentation.
                if (err !== null) {
                    done();
                    return callback(err, '[]');
                }
                var x = [
                    'SELECT key FROM avars',
                    'WHERE box = $1 AND status = $2 AND ' +
                        'last_touch > NOW() - INTERVAL \'' +
                        settings.avar_ttl + ' seconds\''
                ].join(' ');
                client.query(x, params, function (err, results) {
                 // This function needs documentation.
                    done();
                    if ((err !== null) || (results === undefined)) {
                        return callback(err, '[]');
                    }
                    var y = JSON.stringify(results.rows.map(function (row) {
                     // This function needs documentation.
                        return row.key;
                    }));
                    return callback(null, y);
                });
                return;
            });
            return;
        };

        set_avar = function (params, callback) {
         // This function needs documentation.
            pg.connect(connection_string, function (err, client, done) {
             // This function needs documentation.
                if (err !== null) {
                    done();
                    return callback(err);
                }
                var args, sql;
                args = [
                    params[params.length - 1],  // body
                    params[0],                  // box
                    params[1]                   // key
                ];
                sql = 'SELECT upsert_avar($1, $2, $3)';
                if (params.length === 4) {
                    args.push(params[2]);
                    sql = 'SELECT upsert_task($1, $2, $3, $4)';
                }
                client.query(sql, args, function (err) {
                 // This function actually receives a second `results`
                 // parameter, but because `callback` won't use it, we ignore
                 // it here to avoid "unused variable" errors in JS linters.
                    done();
                    return callback(err);
                });
                return;
            });
            return;
        };

        if (cluster.isMaster) {
            pg.connect(connection_string, function (err, client, done) {
             // This function needs documentation.
                if (err !== null) {
                    done();
                    throw err;
                }
                var lines = [

                    'CREATE TABLE IF NOT EXISTS avars (',
                    '   body TEXT NOT NULL,',
                    '   box TEXT NOT NULL,',
                    '   key TEXT NOT NULL,',
                    '   last_touch TIMESTAMP NOT NULL DEFAULT NOW(),',
                    '   status TEXT,',
                    '   PRIMARY KEY (box, key)',
                    ');',

                 /*
                    'DO',
                    '$$',
                    'BEGIN',
                    '   IF NOT EXISTS (',
                    '       SELECT  1',
                    '       FROM    pg_class c',
                    '       JOIN    pg_namespace n ON n.oid = c.relnamespace',
                    '       WHERE   c.relname = \'jobs\'',
                    '       AND     n.nspname = \'public\'',
                    '       ) THEN',
                    '       CREATE INDEX jobs ON public.avars (box, status);',
                    '   END IF;',
                    '   IF NOT EXISTS (',
                    '       SELECT  1',
                    '       FROM    pg_class c',
                    '       JOIN    pg_namespace n ON n.oid = c.relnamespace',
                    '       WHERE   c.relname = \'ltouch\'',
                    '       AND     n.nspname = \'public\'',
                    '       ) THEN',
                    '       CREATE INDEX ltouch ON public.avars (last_touch);',
                    '   END IF;',
                    'END',
                    '$$',
                    'language plpgsql;',
                 */

                    'CREATE OR REPLACE FUNCTION evict_old_avars() ' +
                        'RETURNS trigger AS',
                    '$$',
                    'BEGIN',
                    '   DELETE FROM avars',
                    '   WHERE last_touch < NOW() - INTERVAL \'' +
                            settings.avar_ttl + ' seconds\';',
                    '   RETURN NEW;',
                    'END;',
                    '$$',
                    'language plpgsql;',

                    'DROP TRIGGER IF EXISTS avar_gc ON avars;',
                    'CREATE TRIGGER avar_gc',
                    '   AFTER INSERT ON avars',
                    '   EXECUTE PROCEDURE evict_old_avars();',

                    'CREATE OR REPLACE FUNCTION upsert_avar' +
                        '(body2 TEXT, box2 TEXT, key2 TEXT) RETURNS VOID AS',
                    '$$',
                    'BEGIN',
                    '   LOOP',
                    '       UPDATE avars',
                    '           SET body = body2,' +
                        '           last_touch = NOW(),' +
                        '           status = NULL',
                    '           WHERE box = box2 AND key = key2;',
                    '       IF found THEN',
                    '           RETURN;',
                    '       END IF;',
                    '       BEGIN',
                    '           INSERT INTO avars (body, box, key)',
                    '               VALUES (body2, box2, key2);',
                    '           RETURN;',
                    '       EXCEPTION WHEN unique_violation THEN',
                    '       END;',
                    '   END LOOP;',
                    'END;',
                    '$$',
                    'LANGUAGE plpgsql;',

                    'CREATE OR REPLACE FUNCTION upsert_task' +
                        '(body2 TEXT, box2 TEXT, key2 TEXT, status2 TEXT) ' +
                        'RETURNS VOID AS',
                    '$$',
                    'BEGIN',
                    '   LOOP',
                    '       UPDATE avars',
                    '           SET body = body2,' +
                        '           last_touch = NOW(),' +
                        '           status = status2',
                    '           WHERE box = box2 AND key = key2;',
                    '       IF found THEN',
                    '           RETURN;',
                    '       END IF;',
                    '       BEGIN',
                    '           INSERT INTO avars (body, box, key, status)',
                    '               VALUES (body2, box2, key2, status2);',
                    '           RETURN;',
                    '       EXCEPTION WHEN unique_violation THEN',
                    '       END;',
                    '   END LOOP;',
                    'END;',
                    '$$',
                    'LANGUAGE plpgsql;'

                ];
                client.query(lines.join('\n'), function (err) {
                 // This function also accepts a second argument that contains
                 // the "results" of the query, but because I don't use it, I
                 // have omitted it to avoid irritating JSLint et al.
                    done();
                    if (err !== null) {
                        throw err;
                    }
                    console.log('API: PostgreSQL storage is ready.');
                    return;
                });
                return;
            });
        }

        return {
            collect_garbage: collect_garbage,
            get_avar: get_avar,
            get_list: get_list,
            set_avar: set_avar
        };
    };

    exports.log = function (settings) {
     // This function needs documentation.
        var connection_string = settings.trafficlog_storage.postgres;
        pg.connect(connection_string, function (err, client, done) {
         // This function needs documentation.
            if (err !== null) {
                done();
                throw err;
            }
            if (cluster.isWorker) {
                done();
                return;
            }
            var lines;
            lines = [
                'CREATE EXTENSION IF NOT EXISTS hstore;',
                'CREATE TABLE IF NOT EXISTS traffic (',
                '   id serial PRIMARY KEY,',
                '   doc hstore',
                ');'
            ];
            client.query(lines.join('\n'), function (err) {
             // This function needs documentation.
                if (err !== null) {
                    throw err;
                }
                console.log('LOG: PostgreSQL storage is ready.');
                done();
                return;
            });
            return;
        });
        return function (obj) {
         // This function needs documentation.
            pg.connect(connection_string, function (err, client, done) {
             // This function needs documentation.
                if (err !== null) {
                    done();
                    throw err;
                }
                var doc, key, sql, temp;
                temp = [];
                for (key in obj) {
                    if (obj.hasOwnProperty(key)) {
                     // Technically, this is a bad idea (SQL injection ...).
                        temp.push(key + ' => ' + JSON.stringify(obj[key]));
                    }
                }
                doc = temp.join(', ');
                sql = 'INSERT INTO traffic (doc) VALUES (\'' + doc + '\');';
                client.query(sql, function (err) {
                 // This function needs documentation.
                    if (err !== null) {
                        console.error('Error:', err);
                    }
                    done();
                    return;
                });
                return;
            });
            return;
        };
    };

 // That's all, folks!

    return;

}());

//- vim:set syntax=javascript:
<commit_msg>Log to Postgres using native JSON type!<commit_after>//- JavaScript source code

//- defs-postgres.js ~~
//
//  These definitions assume Postgres 9.2 or later. They also need optimization
//  help from an RDBMS guru.
//
//  Known shortcomings:
//  -   The log storage definition assumes the "uuid-ossp" extension is
//      available.
//
//                                                      ~~ (c) SRW, 25 Sep 2012
//                                                  ~~ last updated 05 Feb 2015

(function () {
    'use strict';

 // Pragmas

    /*jshint maxparams: 3, quotmark: single, strict: true */

    /*jslint indent: 4, maxlen: 80, node: true */

    /*properties
        api, avar_ttl, body, collect_garbage, connect, error, get_avar,
        get_list, isMaster, isWorker, join, key, length, log, map, native,
        persistent_storage, postgres, push, query, rows, set_avar, stringify,
        trafficlog_storage
    */

 // Declarations

    var cluster, pg;

 // Definitions

    cluster = require('cluster');

    try {
     // If the "pg-native" module is installed, use it for a 30% boost in
     // performance. QM lists "pg-native" as an optional dependency.
        pg = require('pg').native;
    } catch (err) {
     // Fall back to the JS (non-native) implementation of the module :-)
        pg = require('pg');
    }

 // Out-of-scope definitions

    exports.api = function (settings) {
     // This function needs documentation.

        var collect_garbage, connection_string, get_avar, get_list,
            set_avar;

        collect_garbage = function () {
         // This function is only a placeholder, now that QM uses an INSERT
         // trigger to evict old rows automatically.
            return;
        };

        connection_string = settings.persistent_storage.postgres;

        get_avar = function (params, callback) {
         // This function needs documentation.
            pg.connect(connection_string, function (err, client, done) {
             // This function needs documentation.
                if (err !== null) {
                    done();
                    return callback(err, '{}');
                }
                var x = [
                    'UPDATE avars SET last_touch = NOW()',
                    'WHERE box = $1 AND key = $2 AND ' +
                        'last_touch > NOW() - INTERVAL \'' +
                        settings.avar_ttl + ' seconds\'',
                    'RETURNING body'
                ].join(' ');
                client.query(x, params, function (err, results) {
                 // This function needs documentation.
                    done();
                    if (err !== null) {
                        return callback(err, '{}');
                    }
                    if (results.rows.length === 0) {
                        return callback(null, '{}');
                    }
                    return callback(null, results.rows[0].body);
                });
                return;
            });
            return;
        };

        get_list = function (params, callback) {
         // This function needs documentation.
            pg.connect(connection_string, function (err, client, done) {
             // This function needs documentation.
                if (err !== null) {
                    done();
                    return callback(err, '[]');
                }
                var x = [
                    'SELECT key FROM avars',
                    'WHERE box = $1 AND status = $2 AND ' +
                        'last_touch > NOW() - INTERVAL \'' +
                        settings.avar_ttl + ' seconds\''
                ].join(' ');
                client.query(x, params, function (err, results) {
                 // This function needs documentation.
                    done();
                    if ((err !== null) || (results === undefined)) {
                        return callback(err, '[]');
                    }
                    var y = JSON.stringify(results.rows.map(function (row) {
                     // This function needs documentation.
                        return row.key;
                    }));
                    return callback(null, y);
                });
                return;
            });
            return;
        };

        set_avar = function (params, callback) {
         // This function needs documentation.
            pg.connect(connection_string, function (err, client, done) {
             // This function needs documentation.
                if (err !== null) {
                    done();
                    return callback(err);
                }
                var args, sql;
                args = [
                    params[params.length - 1],  // body
                    params[0],                  // box
                    params[1]                   // key
                ];
                sql = 'SELECT upsert_avar($1, $2, $3)';
                if (params.length === 4) {
                    args.push(params[2]);
                    sql = 'SELECT upsert_task($1, $2, $3, $4)';
                }
                client.query(sql, args, function (err) {
                 // This function actually receives a second `results`
                 // parameter, but because `callback` won't use it, we ignore
                 // it here to avoid "unused variable" errors in JS linters.
                    done();
                    return callback(err);
                });
                return;
            });
            return;
        };

        if (cluster.isMaster) {
            pg.connect(connection_string, function (err, client, done) {
             // This function needs documentation.
                if (err !== null) {
                    done();
                    throw err;
                }
                var lines = [

                    'CREATE TABLE IF NOT EXISTS avars (',
                    '   body TEXT NOT NULL,',
                    '   box TEXT NOT NULL,',
                    '   key TEXT NOT NULL,',
                    '   last_touch TIMESTAMP NOT NULL DEFAULT NOW(),',
                    '   status TEXT,',
                    '   PRIMARY KEY (box, key)',
                    ');',

                 /*
                    'DO',
                    '$$',
                    'BEGIN',
                    '   IF NOT EXISTS (',
                    '       SELECT  1',
                    '       FROM    pg_class c',
                    '       JOIN    pg_namespace n ON n.oid = c.relnamespace',
                    '       WHERE   c.relname = \'jobs\'',
                    '       AND     n.nspname = \'public\'',
                    '       ) THEN',
                    '       CREATE INDEX jobs ON public.avars (box, status);',
                    '   END IF;',
                    '   IF NOT EXISTS (',
                    '       SELECT  1',
                    '       FROM    pg_class c',
                    '       JOIN    pg_namespace n ON n.oid = c.relnamespace',
                    '       WHERE   c.relname = \'ltouch\'',
                    '       AND     n.nspname = \'public\'',
                    '       ) THEN',
                    '       CREATE INDEX ltouch ON public.avars (last_touch);',
                    '   END IF;',
                    'END',
                    '$$',
                    'language plpgsql;',
                 */

                    'CREATE OR REPLACE FUNCTION evict_old_avars() ' +
                        'RETURNS trigger AS',
                    '$$',
                    'BEGIN',
                    '   DELETE FROM avars',
                    '   WHERE last_touch < NOW() - INTERVAL \'' +
                            settings.avar_ttl + ' seconds\';',
                    '   RETURN NEW;',
                    'END;',
                    '$$',
                    'language plpgsql;',

                    'DROP TRIGGER IF EXISTS avar_gc ON avars;',
                    'CREATE TRIGGER avar_gc',
                    '   AFTER INSERT ON avars',
                    '   EXECUTE PROCEDURE evict_old_avars();',

                    'CREATE OR REPLACE FUNCTION upsert_avar' +
                        '(body2 TEXT, box2 TEXT, key2 TEXT) RETURNS VOID AS',
                    '$$',
                    'BEGIN',
                    '   LOOP',
                    '       UPDATE avars',
                    '           SET body = body2,' +
                        '           last_touch = NOW(),' +
                        '           status = NULL',
                    '           WHERE box = box2 AND key = key2;',
                    '       IF found THEN',
                    '           RETURN;',
                    '       END IF;',
                    '       BEGIN',
                    '           INSERT INTO avars (body, box, key)',
                    '               VALUES (body2, box2, key2);',
                    '           RETURN;',
                    '       EXCEPTION WHEN unique_violation THEN',
                    '       END;',
                    '   END LOOP;',
                    'END;',
                    '$$',
                    'LANGUAGE plpgsql;',

                    'CREATE OR REPLACE FUNCTION upsert_task' +
                        '(body2 TEXT, box2 TEXT, key2 TEXT, status2 TEXT) ' +
                        'RETURNS VOID AS',
                    '$$',
                    'BEGIN',
                    '   LOOP',
                    '       UPDATE avars',
                    '           SET body = body2,' +
                        '           last_touch = NOW(),' +
                        '           status = status2',
                    '           WHERE box = box2 AND key = key2;',
                    '       IF found THEN',
                    '           RETURN;',
                    '       END IF;',
                    '       BEGIN',
                    '           INSERT INTO avars (body, box, key, status)',
                    '               VALUES (body2, box2, key2, status2);',
                    '           RETURN;',
                    '       EXCEPTION WHEN unique_violation THEN',
                    '       END;',
                    '   END LOOP;',
                    'END;',
                    '$$',
                    'LANGUAGE plpgsql;'

                ];
                client.query(lines.join('\n'), function (err) {
                 // This function also accepts a second argument that contains
                 // the "results" of the query, but because I don't use it, I
                 // have omitted it to avoid irritating JSLint et al.
                    done();
                    if (err !== null) {
                        throw err;
                    }
                    console.log('API: PostgreSQL storage is ready.');
                    return;
                });
                return;
            });
        }

        return {
            collect_garbage: collect_garbage,
            get_avar: get_avar,
            get_list: get_list,
            set_avar: set_avar
        };
    };

    exports.log = function (settings) {
     // This function needs documentation.
        var connection_string = settings.trafficlog_storage.postgres;
        pg.connect(connection_string, function (err, client, done) {
         // This function needs documentation.
            if (err !== null) {
                done();
                throw err;
            }
            if (cluster.isWorker) {
                done();
                return;
            }
            var lines;
            lines = [
                'CREATE EXTENSION IF NOT EXISTS "uuid-ossp";',
                'CREATE TABLE IF NOT EXISTS traffic (',
                '   id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),',
                '   doc json NOT NULL',
                ');'
            ];
            client.query(lines.join('\n'), function (err) {
             // This function needs documentation.
                if (err !== null) {
                    throw err;
                }
                console.log('LOG: PostgreSQL storage is ready.');
                done();
                return;
            });
            return;
        });
        return function (obj) {
         // This function needs documentation.
            pg.connect(connection_string, function (err, client, done) {
             // This function needs documentation.
                if (err !== null) {
                    done();
                    throw err;
                }
                var doc, sql;
                doc = JSON.stringify(obj);
                sql = 'INSERT INTO traffic (doc) VALUES (\'' + doc + '\');';
                client.query(sql, function (err) {
                 // This function needs documentation.
                    if (err !== null) {
                        console.error('Error:', err);
                    }
                    done();
                    return;
                });
                return;
            });
            return;
        };
    };

 // That's all, folks!

    return;

}());

//- vim:set syntax=javascript:
<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.downloader = undefined;

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _fs = require('fs');

var _fs2 = _interopRequireDefault(_fs);

var _url = require('url');

var _url2 = _interopRequireDefault(_url);

var _path = require('path');

var _path2 = _interopRequireDefault(_path);

var _debug = require('debug');

var _debug2 = _interopRequireDefault(_debug);

var _async = require('async');

var _async2 = _interopRequireDefault(_async);

var _mkdirp = require('mkdirp');

var _mkdirp2 = _interopRequireDefault(_mkdirp);

var _requestPromise = require('request-promise');

var _requestPromise2 = _interopRequireDefault(_requestPromise);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * @description Validate a Playlist
 * @param {string} playlistContent
 * @returns {boolean}
 */
function isValidPlaylist(playlistContent) {
  return playlistContent.match(/^#EXTM3U/im) !== null;
}

/**
 * @description Validate a URL
 * @param {string} url URL to validate
 * @returns {boolean}
 */
function validateURL(url) {

  var re_weburl = new RegExp('^' +
  // protocol identifier
  '(?:(?:https?)://)' +
  // user:pass authentication
  '(?:\\S+(?::\\S*)?@)?' + '(?:' +
  // IP address exclusion
  // private & local networks
  '(?!(?:10|127)(?:\\.\\d{1,3}){3})' + '(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})' + '(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})' +
  // IP address dotted notation octets
  // excludes loopback network 0.0.0.0
  // excludes reserved space >= 224.0.0.0
  // excludes network & broacast addresses
  // (first & last IP address of each class)
  '(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])' + '(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}' + '(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))' + '|' +
  // host name
  '(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)' +
  // domain name
  '(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*' +
  // TLD identifier
  '(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))' + ')' +
  // port number
  '(?::\\d{2,5})?' +
  // resource path
  '(?:/\\S*)?' + '$', 'i');

  return re_weburl.test(url);
}

/**
 * Strip first slash from a url
 * @param  {String} url URL to strip the slash
 * @return {String} Stripped url
 */
function stripFirstSlash(url) {
  return url.substr(0, 1).replace('/', '') + url.substring(1);
}

/**
 * Strip last slash from a url
 * @param  {String} url URL to strip the slash
 * @return {String} Stripped url
 */
function stripLastSlash(url) {
  return url.substr(-1) + url.substr(0, -1).replace('/', '');
}

var HLSDownloader = function () {
  /**
   * @constructor HLSParser
   * @param  {Object} playlistInfo playlist information to download
   * @return {Object} Error object if any required piece is missing
   */

  function HLSDownloader(playlistInfo) {
    _classCallCheck(this, HLSDownloader);

    if ((typeof playlistInfo === 'undefined' ? 'undefined' : _typeof(playlistInfo)) === 'object' && (playlistInfo.playlistURL === null || playlistInfo.playlistURL === 'undefined' || playlistInfo.playlistURL === '' || !validateURL(playlistInfo.playlistURL))) {
      conosle.log('ERR_VALIDATION: playListURL is required ' + 'or check if your URL is valid or not!!');
    }

    this.playlistURL = playlistInfo.playlistURL;
    this.destination = playlistInfo.destination || null;
    var urls = _url2.default.parse(this.playlistURL, true, true);
    this.hostName = urls.protocol + '//' + urls.hostname + (urls.port ? ':' + urls.port : '');
    this.items = [];
    this.errors = [];
  }

  /**
   * @description initiate download
   * @method {function} startDownload
   * @param {function} callback
   */

  _createClass(HLSDownloader, [{
    key: 'startDownload',
    value: function startDownload(callback) {
      return this.getPlaylist(callback);
    }

    /**
     * @description Download master playlist
     * @method getPlaylist
     * @param {function} callback
     */

  }, {
    key: 'getPlaylist',
    value: function getPlaylist(callback) {

      var self = this;

      _requestPromise2.default.get(self.playlistURL).then(function (body) {

        if (!isValidPlaylist(body)) {
          return callback(new Error('This playlist isn\'t a m3u8 playlist'));
        }

        self.items.push(self.playlistURL.replace(self.hostName + '/', ''));
        self.parseMasterPlaylist(body, callback);
      }).catch(function (err) {
        if (err) {
          var error = new Error('VariantDownloadError');
          error.statusCode = err.statusCode;
          error.uri = err.options.uri;
          return callback(error);
        }
      });
    }

    /**
     * @description Parse master playlist content
     * @method parseMasterPlaylist
     * @param {string} playlistContent
     * @param {function} callback
     */

  }, {
    key: 'parseMasterPlaylist',
    value: function parseMasterPlaylist(playlistContent, callback) {

      var self = this;

      if (playlistContent.match(/^#EXT-X-TARGETDURATION:\d+/im)) {
        this.parseVariantPlaylist(playlistContent);
        this.downloadItems(callback);
      } else {
        try {
          (function () {
            var replacedPlaylistContent = playlistContent.replace(/^#[\s\S].*/igm, '');
            var variants = replacedPlaylistContent.split('\n').filter(function (item) {
              return item !== '';
            });

            var errorCounter = 0;
            var variantCount = variants.length;

            _async2.default.each(variants, function (item, cb) {

              var variantPathObj = _path2.default.dirname(item);
              var variantPath = variantPathObj.substr(0, 1).replace('/', '') + variantPathObj.substring(1);
              var variantUrl = self.hostName + '/' + variantPath + '/' + _path2.default.basename(item);

              _requestPromise2.default.get(variantUrl).then(function (body) {

                if (isValidPlaylist(body)) {
                  self.items.push(variantPath + '/' + _path2.default.basename(item));
                  self.parseVariantPlaylist(variantPath, body);
                  return cb();
                }
              }).catch(function (err) {
                self.errors.push(err.options.uri);

                //check if all variants has error
                if (err && ++errorCounter === variantCount) {
                  return cb(true);
                }

                return cb(null);
              });
            }, function (err) {
              return err ? callback({
                playlistURL: self.playlistURL,
                message: 'No valid Downloadable ' + 'variant exists in master playlist'
              }) : self.downloadItems(callback);
            });
          })();
        } catch (exception) {
          //Catch any syntax error
          return callback(exception);
        }
      }
    }

    /**
     * @description Parse variant playlist content and index the TS chunk to download.
     * @method parseVariantPlaylist
     * @param {string} variantPath
     * @param {string} playlistContent
     */

  }, {
    key: 'parseVariantPlaylist',
    value: function parseVariantPlaylist(variantPath, playlistContent) {
      var replacedPlaylistContent = playlistContent.replace(/^#[\s\S].*/igm, '');
      var items = replacedPlaylistContent.split('\n').filter(function (item) {
        return item !== '';
      }).map(function (item) {
        return variantPath + '/' + _path2.default.basename(item);
      });

      this.items = this.items.concat(items);
    }

    /**
     * @description Download indexed chunks and playlist.
     * @method downloadItems
     * @param {function} callback
     */

  }, {
    key: 'downloadItems',
    value: function downloadItems(callback) {

      var self = this;

      _async2.default.each(this.items, function (item, cb) {

        var variantUrl = self.hostName + '/' + item;

        _requestPromise2.default.get(variantUrl).then(function (downloadedItem) {
          if (self.destination !== null && self.destination !== '' && self.destination !== 'undefined') {
            return self.createItems(variantUrl, downloadedItem, cb);
          }

          downloadedItem = null;
          return cb();
        }).catch(function (err) {
          self.errors.push(err.options.uri);
          return cb(null);
        });
      }, function (err) {
        if (err) {
          return callback({
            playlistURL: self.playlistURL,
            message: 'Internal Server Error from remote'
          });
        }

        if (self.errors.length > 0) {
          return callback(null, {
            message: 'Download done with some errors',
            playlistURL: self.playlistURL,
            errors: self.errors
          });
        }

        return callback(null, {
          message: 'Downloaded successfully',
          playlistURL: self.playlistURL
        });
      });
    }

    /**
     * @description Download indexed chunks and playlist.
     * @method downloadItems
     * @param {function} callback
     */

  }, {
    key: 'createItems',
    value: function createItems(variantURL, content, cb) {

      var self = this;
      var itemPath = variantURL.replace(this.hostName, '');
      var destDirectory = self.destination + _path2.default.dirname(itemPath);
      var filePath = self.destination + '/' + itemPath;
      (0, _mkdirp2.default)(destDirectory, function (err) {
        return err ? cb(err) : _fs2.default.writeFile(filePath, content, cb);
      });
    }
  }]);

  return HLSDownloader;
}();

var downloader = exports.downloader = HLSDownloader;
exports.default = HLSDownloader;
<commit_msg>removed autogenerated hlsParser file<commit_after><|endoftext|>


<commit_before>var dbConnection = require('../databaseSetup.js');

//checks if the user has received any friend requests and any contents to vote.
module.exports.checkUpdates = function(req, res){

  //take the userId information from the request.
  var userId = req.body.userId;

  //prepare the data object to send back with the properties.
  var data = {
    friendRequestCount: undefined,
    pendingCount: undefined
  };

  //define the mysql query to use
  var countFriendRequestQuery = "SELECT * FROM friendRequests WHERE confirmerId = ?";
  var countPendingQuery = "SELECT contentId FROM receivers WHERE receiversId = ?";

  //first, check friendRequests database to check if there is any friend requests
  dbConnection.query(countFriendRequestQuery, userId, function(error, rows){
    if(error){
      res.send(error);
    }else{
      //store the number of the requests in the data object
      data.friendRequestCount = rows.length;
      //second, check receivers datbase to check if there is any pending contents
      dbConnection.query(countPendingQuery, userId, function(error, rows){
        if(error){
          //if there is any error, send back the friend request count at least.
          res.send(data);
        }else{
          //store the number of the pending contents in the data object
          data.pendingCount = rows.length;
          //send back the data to client
          res.send(data);
        }
      });
    }
  });

};<commit_msg>(refactor) add the last line<commit_after>var dbConnection = require('../databaseSetup.js');

//checks if the user has received any friend requests and any contents to vote.
module.exports.checkUpdates = function(req, res){

  //take the userId information from the request.
  var userId = req.body.userId;

  //prepare the data object to send back with the properties.
  var data = {
    friendRequestCount: undefined,
    pendingCount: undefined
  };

  //define the mysql query to use
  var countFriendRequestQuery = "SELECT * FROM friendRequests WHERE confirmerId = ?";
  var countPendingQuery = "SELECT contentId FROM receivers WHERE receiversId = ?";

  //first, check friendRequests database to check if there is any friend requests
  dbConnection.query(countFriendRequestQuery, userId, function(error, rows){
    if(error){
      res.send(error);
    }else{
      //store the number of the requests in the data object
      data.friendRequestCount = rows.length;
      //second, check receivers datbase to check if there is any pending contents
      dbConnection.query(countPendingQuery, userId, function(error, rows){
        if(error){
          //if there is any error, send back the friend request count at least.
          res.send(data);
        }else{
          //store the number of the pending contents in the data object
          data.pendingCount = rows.length;
          //send back the data to client
          res.send(data);
        }
      });
    }
  });

};
<|endoftext|>


<commit_before>'use strict';

const flatten = require('lodash.flatten');
const ON = 'on';
const BEFORE = 'before';
const AFTER = 'after';
const HIERARCHY_SEPARATOR = '.';

/**
 * Listeners by event.
 *
 * [message]: {
 *   before: ...Function,
 *   on: ...Function,
 *   after: ...Function,
 * }
 *
 * @var Object
 */
let listeners = {};

/**
 * Returns all the listeners for a given message. The returned value will be an
 * object whose keys are 'before', 'on' and 'after' of which each will contain
 * an array of functions/listeners.
 *
 * @param String message
 * @return Object
 */
function getListenersFor(message) {
  if (!listeners[message]) listeners[message] = {
    [BEFORE]: [],
    [ON]: [],
    [AFTER]: []
  };
  return listeners[message];
}

/**
 * Returns a list of messages that should be called in order for a specific
 * message
 *
 * @param String message
 * @return String[]
 */
function getHierarchy(message) {
  let parts = message.split(HIERARCHY_SEPARATOR);
  let hierarchy = [parts[0], '*'];
  parts.reduce((message, part) => {
    let prefix = message + HIERARCHY_SEPARATOR;
    let newMessage = prefix + part;
    let wildcard = prefix + '*';
    hierarchy.unshift(newMessage, wildcard);
    return newMessage;
  });
  return hierarchy;
}

/**
 * Adds a listener to a specific part of an event's lifecycle.
 *
 * @param String part
 * @param String message
 * @param Function fn
 */
function onPart(part, message, fn) {
  getListenersFor(message)[part].push(fn);
}

/**
 * Adds a listener to the event.
 *
 * @param String message
 * @param Function fn
 */
function on(message, fn) {
  onPart(ON, message, fn);
}

/**
 * Adds a listener to the end of the event lifecycle.
 *
 * @param String message
 * @param Function fn
 */
function before(message, fn) {
  onPart(BEFORE, message, fn);
}

/**
 * Adds a listener to the end of the event lifecycle.
 *
 * @param String message
 * @param Function fn
 */
function after(message, fn) {
  onPart(AFTER, message, fn);
}

/**
 * Will call the listener once each of the specified events have been emitted.
 * The listeners are given as an object, where each key will specify the part of
 * the event lifecycle and the value is an array of event names/messages.
 *
 * ```
 * all({
 *   before: ['foo', 'bar'],
 *   on: ['another'],
 *   after: ['event']
 * }, ({foo, bar, another, event}) => {
 *   // You'll receive data for each event that fired
 * });
 * ```
 *
 * @param Object<before: String[], on: String[], after: String[]> messages
 * @param Function fn
 */
function all(messages, fn) {
  let toDo;
  let dataCollection;
  let allMessages = Object
    .keys(messages)
    .reduce((all, part) => all.concat(messages[part]), []);

  init();

  function subscriber(message, ...data) {
    dataCollection[message] = data;
    toDo--;
    if (!toDo) {
      fn(dataCollection);
      init();
    }
  }

  function registerSubscribers(prop, method) {
    if (messages[prop]) messages[prop].forEach(message => {
      method(message, subscriber);
    });
  }

  function init() {
    toDo = allMessages.length;
    dataCollection = {};
    registerSubscribers('before', onceBefore);
    registerSubscribers('on', once);
    registerSubscribers('after', onceAfter);
  }
}

/**
 * Removes a listener from a given event.
 *
 * @param String message
 * @param Function fn
 * @return Number
 */
function removeListener(message, fn) {
  let listeners = getListenersFor(message);
  let removed = 0;
  for (let key in listeners) {
    let set = listeners[key];
    let index = set.indexOf(fn);
    if (index !== -1) {
      set.splice(index, 1);
      removed++;
      break;
    }
  }
  return removed;
}

/**
 * Removes all listeners from a given event.
 *
 * @param String message
 * @return Number
 */
function removeAllListeners(message) {
  let all = listeners[message];
  let amount = all ? all.length : 0;
  delete listeners[message];
  return amount;
}

/**
 * Removes the specified listener from a given event. If no listener is
 * specified, all will be removed.
 *
 * @param String message
 * @param Function fn
 * @return Number
 */
function off(message, fn) {
  return fn ? removeListener(message, fn) : removeAllListeners(message);
}

/**
 * Adds a listener to a specific part of the event lifecycle and removes it
 * as soon as it's been called.
 *
 * @param Function subscribe
 * @param String message
 * @param Function fn
 */
function oncePart(subscribe, message, fn) {
  let subscriber = (...args) => {
    off(message, subscriber);
    return fn(...args);
  };
  subscribe(message, subscriber);
}

/**
 * Adds the listener to the event for just one emittion.
 *
 * @param String message
 * @param Function fn
 */
function once(message, fn) {
  oncePart(on, message, fn);
}

/**
 * Adds a listener to the beginning of the event lifecycle for just one emittion.
 *
 * @param String message
 * @param Function fn
 */
function onceBefore(message, fn) {
  oncePart(before, message, fn);
}

/**
 * Adds a listener to the end of the event lifecycle for just one emittion.
 *
 * @param String message
 * @param Function fn
 */
function onceAfter(message, fn) {
  oncePart(after, message, fn);
}

/**
 * Creates an emitter based on the event name/message and data. The emitter
 * can then be used to emit each part of the lifecycle.
 *
 * @param String message
 * @param Any[] data
 * @return Function
 */
function createEmitter(message, data) {
  let call = fn => fn(message, ...data);
  let hierarchy = getHierarchy(message);
  return part => Promise.all(flatten(
    hierarchy.map(message => getListenersFor(message)[part].map(call))
  ));
}

/**
 * Fires off the lifecycle of an event.
 *
 * @param String message
 * @param Any ...data
 * @return Promise
 */
function emit(message, ...data) {
  let emit = createEmitter(message, data);
  return emit(BEFORE)
    .then(() => emit(ON))
    .then(() => emit(AFTER));
}

/**
 * Registering that one event will trigger another, passing all data.
 *
 * @param String trigger
 * @param String[] messages
 */
function triggers(trigger, messages) {
  on(trigger, (_, ...data) => (
    messages.map(message => emit(message, ...data))
  ));
}

Object.assign(exports, {
  after, all, before, emit, off, on, once, onceAfter, onceBefore, triggers
});
<commit_msg>Triggers<commit_after>'use strict';

const flatten = require('lodash.flatten');
const ON = 'on';
const BEFORE = 'before';
const AFTER = 'after';
const HIERARCHY_SEPARATOR = '.';

/**
 * Listeners by event.
 *
 * [message]: {
 *   before: ...Function,
 *   on: ...Function,
 *   after: ...Function,
 * }
 *
 * @var Object
 */
let listeners = {};

/**
 * Returns all the listeners for a given message. The returned value will be an
 * object whose keys are 'before', 'on' and 'after' of which each will contain
 * an array of functions/listeners.
 *
 * @param String message
 * @return Object
 */
function getListenersFor(message) {
  if (!listeners[message]) listeners[message] = {
    [BEFORE]: [],
    [ON]: [],
    [AFTER]: []
  };
  return listeners[message];
}

/**
 * Returns a list of messages that should be called in order for a specific
 * message
 *
 * @param String message
 * @return String[]
 */
function getHierarchy(message) {
  let parts = message.split(HIERARCHY_SEPARATOR);
  let hierarchy = [parts[0], '*'];
  parts.reduce((message, part) => {
    let prefix = message + HIERARCHY_SEPARATOR;
    let newMessage = prefix + part;
    let wildcard = prefix + '*';
    hierarchy.unshift(newMessage, wildcard);
    return newMessage;
  });
  return hierarchy;
}

/**
 * Adds a listener to a specific part of an event's lifecycle.
 *
 * @param String part
 * @param String message
 * @param Function fn
 */
function onPart(part, message, fn) {
  getListenersFor(message)[part].push(fn);
}

/**
 * Adds a listener to the event.
 *
 * @param String message
 * @param Function fn
 */
function on(message, fn) {
  onPart(ON, message, fn);
}

/**
 * Adds a listener to the beginning of the event lifecycle.
 *
 * @param String message
 * @param Function fn
 */
function before(message, fn) {
  onPart(BEFORE, message, fn);
}

/**
 * Adds a listener to the end of the event lifecycle.
 *
 * @param String message
 * @param Function fn
 */
function after(message, fn) {
  onPart(AFTER, message, fn);
}

/**
 * Will call the listener once each of the specified events have been emitted.
 * The events are given as an object, where each key will specify the part of
 * the event lifecycle and the value is an array of event names/messages.
 *
 * ```
 * all({
 *   before: ['foo', 'bar'],
 *   on: ['another'],
 *   after: ['event']
 * }, ({foo, bar, another, event}) => {
 *   // You'll receive data for each event that fired
 * });
 * ```
 *
 * @param Object<before: String[], on: String[], after: String[]> messages
 * @param Function fn
 */
function all(messages, fn) {
  let toDo;
  let dataCollection;
  let size = Object
    .keys(messages)
    .reduce((size, part) => size + messages[part].length, 0);

  init();

  function subscriber(message, ...data) {
    dataCollection[message] = data;
    toDo--;
    if (!toDo) {
      fn(dataCollection);
      init();
    }
  }

  function registerSubscribers(prop, method) {
    if (messages[prop]) messages[prop].forEach(message => {
      method(message, subscriber);
    });
  }

  function init() {
    toDo = size;
    dataCollection = {};
    registerSubscribers('before', onceBefore);
    registerSubscribers('on', once);
    registerSubscribers('after', onceAfter);
  }
}

/**
 * Removes a listener from a given event.
 *
 * @param String message
 * @param Function fn
 * @return Number
 */
function removeListener(message, fn) {
  let listeners = getListenersFor(message);
  let removed = 0;
  for (let key in listeners) {
    let set = listeners[key];
    let index = set.indexOf(fn);
    if (index !== -1) {
      set.splice(index, 1);
      removed++;
      break;
    }
  }
  return removed;
}

/**
 * Removes all listeners from a given event.
 *
 * @param String message
 * @return Number
 */
function removeAllListeners(message) {
  let all = listeners[message];
  let amount = all ? all.length : 0;
  delete listeners[message];
  return amount;
}

/**
 * Removes the specified listener from a given event. If no listener is
 * specified, all will be removed.
 *
 * @param String message
 * @param Function fn
 * @return Number
 */
function off(message, fn) {
  return fn ? removeListener(message, fn) : removeAllListeners(message);
}

/**
 * Adds a listener to a specific part of the event lifecycle and removes it
 * as soon as it's been called.
 *
 * @param Function subscribe
 * @param String message
 * @param Function fn
 */
function oncePart(subscribe, message, fn) {
  let subscriber = (...args) => {
    off(message, subscriber);
    return fn(...args);
  };
  subscribe(message, subscriber);
}

/**
 * Adds the listener to the event for just one emittion.
 *
 * @param String message
 * @param Function fn
 */
function once(message, fn) {
  oncePart(on, message, fn);
}

/**
 * Adds a listener to the beginning of the event lifecycle for just one emittion.
 *
 * @param String message
 * @param Function fn
 */
function onceBefore(message, fn) {
  oncePart(before, message, fn);
}

/**
 * Adds a listener to the end of the event lifecycle for just one emittion.
 *
 * @param String message
 * @param Function fn
 */
function onceAfter(message, fn) {
  oncePart(after, message, fn);
}

/**
 * Creates an emitter based on the event name/message and data. The emitter
 * can then be used to emit each part of the lifecycle.
 *
 * @param String message
 * @param Any[] data
 * @return Function
 */
function createEmitter(message, data) {
  let call = fn => fn(message, ...data);
  let hierarchy = getHierarchy(message);
  return part => Promise.all(flatten(
    hierarchy.map(message => getListenersFor(message)[part].map(call))
  ));
}

/**
 * Fires off the lifecycle of an event.
 *
 * @param String message
 * @param Any ...data
 * @return Promise
 */
function emit(message, ...data) {
  let emit = createEmitter(message, data);
  return emit(BEFORE)
    .then(() => emit(ON))
    .then(() => emit(AFTER));
}

/**
 * Subscribes emittion of an array of events to another event. All data will be
 * passed to the emittions.
 *
 * @param Function subscribe
 * @param String message
 * @param String[] triggers
 */
function triggersPart(subscribe, message, triggers) {
  subscribe(message, (_, ...data) => (
    triggers.map(message => emit(message, ...data))
  ));
}

/**
 * Registering that one event will trigger another, passing all data.
 *
 * @param String trigger
 * @param String[] messages
 */
function triggers(trigger, messages) {
  triggersPart(on, trigger, messages);
}

function triggersAfter(trigger, messages) {
  triggersPart(after, trigger, messages);
}

function triggersBefore(trigger, messages) {
  triggersPart(before, trigger, messages);
}

function triggersOnce(trigger, messages) {
  triggersPart(once, trigger, messages);
}

function triggersOnceAfter(trigger, messages) {
  triggersPart(onceAfter, trigger, messages);
}

function triggersOnceBefore(trigger, messages) {
  triggersPart(onceBefore, trigger, messages);
}

Object.assign(exports, {
  after, all, before, emit, off, on, once, onceAfter, onceBefore, triggers,
  triggersAfter, triggersBefore, triggersOnce, triggersOnceAfter,
  triggersOnceBefore
});
<|endoftext|>


<commit_before>'use babel';

/* @flow*/

import { Observable } from 'rxjs';
import globToRegex from 'glob-to-regexp';
import { TEST, errorAction, startTestAction } from '../actions';
import { convertWindowsPathToUnixPath } from '../../helpers';
import type { Store, Tester, TesterAction, TesterState } from '../../types';

export default function test(action$: Observable<TesterAction>, store: Store): Observable<TesterAction> {
  return action$.ofType(TEST)
    .debounceTime(100)
    .filter(() => !store.getState().testRunning)
    .switchMap(() => {
      const currentState: TesterState = store.getState();
      const filePath = currentState.editor ? currentState.editor.getPath() : '';
      if (!filePath) {
        return Observable.empty();
      }
      return Observable.from(currentState.testers)
        .filter((tester: Tester) =>
          tester.scopes.some(scope => globToRegex(scope).test(convertWindowsPathToUnixPath(filePath))))
        .isEmpty()
        .switchMap((isEmpty: boolean) => {
          if (isEmpty) {
            return Observable.empty();
          }
          return Observable.of(startTestAction(false));
        });
    })
    .catch(err => Observable.of(errorAction(err)));
}
<commit_msg>increace delay<commit_after>'use babel';

/* @flow*/

import { Observable } from 'rxjs';
import globToRegex from 'glob-to-regexp';
import { TEST, errorAction, startTestAction } from '../actions';
import { convertWindowsPathToUnixPath } from '../../helpers';
import type { Store, Tester, TesterAction, TesterState } from '../../types';

export default function test(action$: Observable<TesterAction>, store: Store): Observable<TesterAction> {
  return action$.ofType(TEST)
    .debounceTime(500)
    .filter(() => !store.getState().testRunning)
    .switchMap(() => {
      const currentState: TesterState = store.getState();
      const filePath = currentState.editor ? currentState.editor.getPath() : '';
      if (!filePath) {
        return Observable.empty();
      }
      return Observable.from(currentState.testers)
        .filter((tester: Tester) =>
          tester.scopes.some(scope => globToRegex(scope).test(convertWindowsPathToUnixPath(filePath))))
        .isEmpty()
        .switchMap((isEmpty: boolean) => {
          if (isEmpty) {
            return Observable.empty();
          }
          return Observable.of(startTestAction(false));
        });
    })
    .catch(err => Observable.of(errorAction(err)));
}
<|endoftext|>


<commit_before>/*
 * Copyrights phwang
 * Written by Paul Hwang
 * File name: express_module.js
 */

module.exports = {
    post: function (req, res) {
        processPost(req, res);
    },

    get: function (req, res) {
        processGet(req, res);
    },

    not_found: function (req, res) {
        processNotFound(req, res);
    },

    failure: function (req, res) {
        processFailure(err, req, res, next);
    },
};

var util = require("./util_module.js");
var queue = require("./queue_module.js");
var ring = require("./ring_module.js");
var account_mgr = require("./session_mgr_module.js");
var link_mgr = require("./link_mgr_module.js");
var express = require('express');
var bodyParser = require('body-parser');
var state;

function processPost(req, res) {
    var my_link_id, my_session, his_session;

    debug(false, "processPost", "start");
    debug(false, "processPost", "my_name=" + req.body.my_name + " link_id=" + req.body.link_id);
    state = "processPost start";

    my_link_id = Number(req.body.link_id);
    my_link = link_mgr.search(req.body.my_name, my_link_id);
    if (!my_link) {
        abend("processPost", "null my_link");
        return;
    }
    if (my_link.link_id === 0) {
        abend("processPost", "null my_link = 0");
        return;
    }

    var my_session_id = Number(req.body.session_id);
    my_session = account_mgr.search(req.body.my_name, req.body.his_name, my_session_id);
    if (!my_session) {
        abend("processPost", "null my_session");
        return;
    }
    if (my_session.session_id === 0) {
        abend("processPost", "null my_session = 0");
        return;
    }
    logit("processPost", "link=" + req.body.link_id + " session=" + req.body.session_id + " "  + req.body.my_name + "=>" + req.body.his_name + " " + req.body.data + " " + req.body.xmt_seq + "=" + my_session.up_seq);
    if (req.body.my_name === req.body.his_name) {
        his_session = my_session;
    }
    else {
        his_session = account_mgr.search(req.body.his_name, req.body.my_name, -1);
        if (!his_session) {
            abend("processPost", "null his_session");
            return;
        }
        if (his_session.session_id === 0) {
            abend("processPost", "null his_session = 0");
            return;
        }
    }

    if (req.body.xmt_seq === my_session.up_seq) {
        queue.enqueue(his_session.queue, req.body.data);
        ring.enqueue(his_session.ring, req.body.data);
        my_session.up_seq += 1;
    } else if (req.body.xmt_seq < my_session.up_seq) {
         if (req.body.xmt_seq === 0) {
            queue.enqueue(his_session.queue, req.body.data);
            ring.enqueue(his_session.ring, req.body.data);
            my_session.up_seq = 1;
            logit("processPost", req.body.data + " post " + req.body.xmt_seq + " reset");
        } else {
            logit("processPost", req.body.data + " post " + req.body.xmt_seq + " dropped");
        }
    } else {
        logit("***abend: processPost", req.body.data + " post seq=" + req.body.xmt_seq + " dropped");
    }
    state = "processPost end";
    debug(false, "processPost", "end");
}

function processGet (req, res) {
    if (req.headers.setup_link === "yes") {
        setupLink(req, res);
        return;
    }

    if (req.headers.setup_session === "yes") {
        setupSession(req, res);
        return;
    }

    debug(false, "processGet ", "start");
    debug(false, "processGet ", "link=" + req.headers.session_id + " "  + req.headers.his_name + "=>" + req.headers.my_name);
    state = "processGet start";

    var my_link_id, session_id;

    my_link_id = Number(req.headers.link_id);
    my_link = link_mgr.search(req.headers.my_name, my_link_id);
    if (!my_link) {
        abend("processGet", "null my_link");
        return;
    }
    if (my_link.link_id === 0) {
        abend("processGet", "null my_link = 0");
        return;
    }

    session_id = Number(req.headers.session_id);
    var my_session = account_mgr.search(req.headers.my_name, req.headers.his_name, session_id);
    if (!my_session) {
        abend("processGet", "null my_session");
        return;
    }
    if (my_session.session_id === 0) {
        abend("processGet", "null my_session = 0");
        return;
    }
    if (!my_session.queue) {
        abend("processGet", "null queue");
        return;
    }
    res.type('application/json');
    state = "get 2000";
    var data = queue.dequeue(my_session.queue);
    state = "get 3000";
    var data1 = ring.dequeue(my_session.ring);
    state = "get 4000";
    if (data !== data1) {
        logit("*****Abend: processGet", "queue and ring not match");
    }
    if (!data) {
        //logit("processGet", "null data");
        return;
    }
    if (!data1) {
        //logti("processGet", "null data1");
        return;
    }

    logit("processGet ", "link=" + req.headers.link_id + " session=" + req.headers.session_id + " "  + req.headers.his_name + "=>" + req.headers.my_name + " " + data);
    res.send(data);
    state = "processGet end";
    debug(false, "processGet ", "end");
}

function setupLink (req, res) {
    state = "setupLink start";
    var link, link_id_str;
    link = link_mgr.search_and_create(req.headers.my_name, 0);
    if (!link) {
        abend("setupLink", "null link");
        return;
    }
    link_id_str = "" + link.link_id;
    res.send(link_id_str);
    logit("setupLink  ", "my_name=" + req.headers.my_name + " link=" + link.link_id);
    state = "setupLink end";
}

function setupSession (req, res) {
    state = "setupSession start";
    var session, session_id_str;
    session = account_mgr.search_and_create(req.headers.my_name, req.headers.his_name, 0);
    if (!session) {
        abend("setupSession", "null session");
        return;
    }
    session_id_str = "" + session.session_id;
    res.send(session_id_str);
    logit("setupSession", req.headers.his_name + "=>" + req.headers.my_name);
    state = "setupSession end";
}

function processNotFound (req, res) {
    logit("processNotFound", "use" + req);
    res.type('text/plain');
    res.status(404);
    res.send('Not Found');
}

function processFailure (err, req, res, next) {
    logit("processFailure", state);
}

function debug(debug_val, str1_val, str2_val) {
    if (debug_val) {
        logit(str1_val, "==" + str2_val);
    }
}

function logit (str1_val, str2_val) {
    return util.utilLogit("NodeMain." + str1_val, str2_val);
}

function abend (str1_val, str2_val) {
    return util.utilAbend("NodeMain." + str1_val, str2_val);
}
<commit_msg>server disp<commit_after>/*
 * Copyrights phwang
 * Written by Paul Hwang
 * File name: express_http_module.js
 */

module.exports = {
    post: function (req, res) {
        processPost(req, res);
    },

    get: function (req, res) {
        processGet(req, res);
    },

    not_found: function (req, res) {
        processNotFound(req, res);
    },

    failure: function (req, res) {
        processFailure(err, req, res, next);
    },
};

var util = require("./util_module.js");
var queue = require("./queue_module.js");
var ring = require("./ring_module.js");
var account_mgr = require("./session_mgr_module.js");
var link_mgr = require("./link_mgr_module.js");
var express = require('express');
var bodyParser = require('body-parser');
var state;

function processPost(req, res) {
    var my_link_id, my_session, his_session;

    debug(false, "processPost", "start");
    debug(false, "processPost", "my_name=" + req.body.my_name + " link_id=" + req.body.link_id);
    state = "processPost start";

    my_link_id = Number(req.body.link_id);
    my_link = link_mgr.search(req.body.my_name, my_link_id);
    if (!my_link) {
        abend("processPost", "null my_link");
        return;
    }
    if (my_link.link_id === 0) {
        abend("processPost", "null my_link = 0");
        return;
    }

    var my_session_id = Number(req.body.session_id);
    my_session = account_mgr.search(req.body.my_name, req.body.his_name, my_session_id);
    if (!my_session) {
        abend("processPost", "null my_session");
        return;
    }
    if (my_session.session_id === 0) {
        abend("processPost", "null my_session = 0");
        return;
    }

    logit("processPost", "(" + req.body.link_id + "," + req.body.session_id + ") "  + req.body.my_name + "=>" + req.body.his_name + " {" + req.body.data + "} " + req.body.xmt_seq + "=" + my_session.up_seq);

    if (req.body.my_name === req.body.his_name) {
        his_session = my_session;
    }
    else {
        his_session = account_mgr.search(req.body.his_name, req.body.my_name, -1);
        if (!his_session) {
            abend("processPost", "null his_session");
            return;
        }
        if (his_session.session_id === 0) {
            abend("processPost", "null his_session = 0");
            return;
        }
    }

    if (req.body.xmt_seq === my_session.up_seq) {
        queue.enqueue(his_session.queue, req.body.data);
        ring.enqueue(his_session.ring, req.body.data);
        my_session.up_seq += 1;
    } else if (req.body.xmt_seq < my_session.up_seq) {
         if (req.body.xmt_seq === 0) {
            queue.enqueue(his_session.queue, req.body.data);
            ring.enqueue(his_session.ring, req.body.data);
            my_session.up_seq = 1;
            logit("processPost", req.body.data + " post " + req.body.xmt_seq + " reset");
        } else {
            logit("processPost", req.body.data + " post " + req.body.xmt_seq + " dropped");
        }
    } else {
        logit("***abend: processPost", req.body.data + " post seq=" + req.body.xmt_seq + " dropped");
    }
    state = "processPost end";
    debug(false, "processPost", "end");
}

function processGet (req, res) {
    if (req.headers.setup_link === "yes") {
        setupLink(req, res);
        return;
    }

    if (req.headers.setup_session === "yes") {
        setupSession(req, res);
        return;
    }

    debug(false, "processGet ", "start");
    debug(false, "processGet ", "link=" + req.headers.session_id + " "  + req.headers.his_name + "=>" + req.headers.my_name);
    state = "processGet start";

    var my_link_id, session_id;

    my_link_id = Number(req.headers.link_id);
    my_link = link_mgr.search(req.headers.my_name, my_link_id);
    if (!my_link) {
        abend("processGet", "null my_link");
        return;
    }
    if (my_link.link_id === 0) {
        abend("processGet", "null my_link = 0");
        return;
    }

    session_id = Number(req.headers.session_id);
    var my_session = account_mgr.search(req.headers.my_name, req.headers.his_name, session_id);
    if (!my_session) {
        abend("processGet", "null my_session");
        return;
    }
    if (my_session.session_id === 0) {
        abend("processGet", "null my_session = 0");
        return;
    }
    if (!my_session.queue) {
        abend("processGet", "null queue");
        return;
    }
    res.type('application/json');
    state = "get 2000";
    var data = queue.dequeue(my_session.queue);
    state = "get 3000";
    var data1 = ring.dequeue(my_session.ring);
    state = "get 4000";
    if (data !== data1) {
        logit("*****Abend: processGet", "queue and ring not match");
    }
    if (!data) {
        //logit("processGet", "null data");
        return;
    }
    if (!data1) {
        //logti("processGet", "null data1");
        return;
    }

    logit("processGet ", "(" + req.headers.link_id + "," + req.headers.session_id + ") "  + req.headers.his_name + "=>" + req.headers.my_name + " {" + data + "}");
    res.send(data);
    state = "processGet end";
    debug(false, "processGet ", "end");
}

function setupLink (req, res) {
    state = "setupLink start";
    var link, link_id_str;
    link = link_mgr.search_and_create(req.headers.my_name, 0);
    if (!link) {
        abend("setupLink", "null link");
        return;
    }
    link_id_str = "" + link.link_id;
    res.send(link_id_str);
    logit("setupLink  ", "my_name=" + req.headers.my_name + " link=" + link.link_id);
    state = "setupLink end";
}

function setupSession (req, res) {
    state = "setupSession start";
    var session, session_id_str;
    session = account_mgr.search_and_create(req.headers.my_name, req.headers.his_name, 0);
    if (!session) {
        abend("setupSession", "null session");
        return;
    }
    session_id_str = "" + session.session_id;
    res.send(session_id_str);
    logit("setupSession", req.headers.his_name + "=>" + req.headers.my_name);
    state = "setupSession end";
}

function processNotFound (req, res) {
    logit("processNotFound", "use" + req);
    res.type('text/plain');
    res.status(404);
    res.send('Not Found');
}

function processFailure (err, req, res, next) {
    logit("processFailure", state);
}

function debug(debug_val, str1_val, str2_val) {
    if (debug_val) {
        logit(str1_val, "==" + str2_val);
    }
}

function logit (str1_val, str2_val) {
    return util.utilLogit("NodeMain." + str1_val, str2_val);
}

function abend (str1_val, str2_val) {
    return util.utilAbend("NodeMain." + str1_val, str2_val);
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import Icon from 'atoms/Icon';
import Modal from 'molecules/Modal';
import styles from './tooltip.module.scss';

class Tooltip extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      modalIsOpen: false,
      visible: false
    };
  }

  componentDidMount() {
    document.addEventListener('mousedown', this.hide);
  }

  componentWillUnmount() {
    document.removeEventListener('mousedown', this.hide);
  }

  setWrapperRef = (node) => {
    this.ref = node;
  }

  openModal = () => {
    (window.innerWidth <= 768) && this.setState({
      modalIsOpen: true
    });
  }

  closeModal = () => {
    this.setState({
      modalIsOpen: false
    });
  }

  toggleVisibility = (e) => {
    e.stopPropagation();
    this.setState({ visible: !this.state.visible });
    this.props.onClick && this.props.onClick(e);
  };

  hide = (e) => {
    if (this.ref && !this.ref.contains(e.target)) {
      e.stopPropagation();
      this.setState({ visible: false });
    }
  };

  handleClick = e => window.innerWidth <= 768 ? this.openModal() : this.toggleVisibility(e);

  render() {
    const {
      children,
      className,
      left,
      right,
      text,
      hoverMessageClassName,
      inline,
      tooltipIconSize,
      revealOnClick
    } = this.props;

    return (

        <span
          onClick={revealOnClick ? this.handleClick : this.openModal}
          className={classnames(
            !revealOnClick && styles['tooltip-wrapper'],
            this.state.visible && styles.reveal,
            inline && styles[`inline-${inline}`],
            className
          )}
          ref={this.setWrapperRef}
        >
          {
            text ||
              <Icon
                icon='tooltip'
                className={styles['tooltip']}
                inline={inline}
                height={`${tooltipIconSize}px`}
                width={`${tooltipIconSize}px`}
              />
          }

            { children }

        <Modal
          header='Learn more'
          onRequestClose={this.closeModal}
          isOpen={this.state.modalIsOpen}
          contentLabel=''
        >
          {children}
        </Modal>

    );
  }
}

Tooltip.propTypes = {

  /**
   * This prop will add a new className to any inherent classNames
   * provided in the component's index.js file.
   */
  className: PropTypes.string,

  /**
   * render left-side variant
   */
  left: PropTypes.bool,

  /**
   * render right-side variant
   */
  right: PropTypes.bool,
  /**
   * onClick will override the default `openModal` click handler
   */
  onClick: PropTypes.func,
  /**
   * defaults to a question mark Icon
   */
  text: PropTypes.node,
  /**
   * className for the hover message
   */
  hoverMessageClassName: PropTypes.string,

  /**
   * adds margin to left or right when Tooltip is inline
   */
  inline: PropTypes.oneOf([
    'left', 'right',
  ]),

  /**
   * Changes height and width of default Tooltip icon. Provide a pixel amount as a number (without the units)
   */
  tooltipIconSize: PropTypes.number,

  /**
   * When viewport is not mobile and revealOnClick prop is present, reveals tooltip message on click only
   */
  revealOnClick: PropTypes.bool
};

Tooltip.defaultProps = {
  tooltipIconSize: 12,
};

export default Tooltip;
<commit_msg>Update Tooltip onClick fallback<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import Icon from 'atoms/Icon';
import Modal from 'molecules/Modal';
import styles from './tooltip.module.scss';

class Tooltip extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      modalIsOpen: false,
      visible: false
    };
  }

  componentDidMount() {
    document.addEventListener('mousedown', this.hide);
  }

  componentWillUnmount() {
    document.removeEventListener('mousedown', this.hide);
  }

  setWrapperRef = (node) => {
    this.ref = node;
  }

  openModal = (e) => {
    (window.innerWidth <= 768) && this.setState({
      modalIsOpen: true
    });
    this.props.onClick && this.props.onClick(e, true);
  }

  closeModal = () => {
    this.setState({
      modalIsOpen: false
    });
  }

  toggleVisibility = (e) => {
    e.stopPropagation();
    this.setState({ visible: !this.state.visible });
    this.props.onClick && this.props.onClick(e, !this.state.visible);
  };

  hide = (e) => {
    if (this.ref && !this.ref.contains(e.target)) {
      e.stopPropagation();
      this.setState({ visible: false });
    }
  };

  handleClick = e => window.innerWidth <= 768 ? this.openModal(e) : this.toggleVisibility(e);

  render() {
    const {
      children,
      className,
      left,
      right,
      text,
      hoverMessageClassName,
      inline,
      tooltipIconSize,
      revealOnClick
    } = this.props;

    return (

        <span
          onClick={revealOnClick ? this.handleClick : this.openModal}
          className={classnames(
            !revealOnClick && styles['tooltip-wrapper'],
            this.state.visible && styles.reveal,
            inline && styles[`inline-${inline}`],
            className
          )}
          ref={this.setWrapperRef}
        >
          {
            text ||
              <Icon
                icon='tooltip'
                className={styles['tooltip']}
                inline={inline}
                height={`${tooltipIconSize}px`}
                width={`${tooltipIconSize}px`}
              />
          }

            { children }

        <Modal
          header='Learn more'
          onRequestClose={this.closeModal}
          isOpen={this.state.modalIsOpen}
          contentLabel=''
        >
          {children}
        </Modal>

    );
  }
}

Tooltip.propTypes = {

  /**
   * This prop will add a new className to any inherent classNames
   * provided in the component's index.js file.
   */
  className: PropTypes.string,

  /**
   * render left-side variant
   */
  left: PropTypes.bool,

  /**
   * render right-side variant
   */
  right: PropTypes.bool,
  /**
   * onClick will override the default `openModal` click handler
   */
  onClick: PropTypes.func,
  /**
   * defaults to a question mark Icon
   */
  text: PropTypes.node,
  /**
   * className for the hover message
   */
  hoverMessageClassName: PropTypes.string,

  /**
   * adds margin to left or right when Tooltip is inline
   */
  inline: PropTypes.oneOf([
    'left', 'right',
  ]),

  /**
   * Changes height and width of default Tooltip icon. Provide a pixel amount as a number (without the units)
   */
  tooltipIconSize: PropTypes.number,

  /**
   * When viewport is not mobile and revealOnClick prop is present, reveals tooltip message on click only
   */
  revealOnClick: PropTypes.bool
};

Tooltip.defaultProps = {
  tooltipIconSize: 12,
};

export default Tooltip;
<|endoftext|>