Example #1
0
  function onResponse(stream) {
    // Clean up request.
    ee.removeListener('requestError', onRequestError);
    ee.removeListener('responseError', onResponseError);
    delete self._req;

    // Parse JSON with JStream.
    var jstream = new JStream();

    // Listen for other errorneous events.
    function onError(err) {
      self.reconnect('exponential');
      if (self.id) {
        err.streamid = self.id;
        err.streamtype = self.type;
      }
      self.emit('error', err);
    }

    function onResponseEnd() {
      self.reconnect('exponential');
      self.emit('end');
    }

    function onResponseClose() {
      self.reconnect('exponential');
      self.emit('end');
    }

    // Keep track of the last time a `data` event occurred to make sure
    // the stream does not time out.
    function onStreamTimeout() {
      self.reconnect('linear');
      self.emit('timeout');
    }

    function onData(data) {
      self._ondata(data);
      clearTimeout(timeout);
      timeout = setTimeout(onStreamTimeout, constants.STREAM_TIMEOUT);
    }

    var timeout = setTimeout(onStreamTimeout, constants.STREAM_TIMEOUT);
    jstream.on('data', onData);

    // Clean up everything after this stream is not used anymore.
    self._cleanup = function cleanup() {
      self.connected = false;
      stream.removeListener('error', onError);
      stream.removeListener('end', onResponseEnd);
      stream.removeListener('close', onResponseClose);
      stream.removeListener('data', onData);
      stream.destroy();
      jstream.removeListener('error', onError);
      clearTimeout(timeout);
      delete self._stream;
      delete self._cleanup;
    };

    stream.on('end', onResponseEnd);
    stream.on('close', onResponseClose);
    stream.pipe(jstream);
    stream.on('error', onError);
    jstream.on('error', onError);

    // Label as connected.
    self._stream = stream;
    self.connected = true;
    self.emit('connect');

  }
Example #2
0
    crequest(link, function(err, body) {
      if (err) return callback(err);

      var jsonStr = util.between(body, 'ytplayer.config = ', '</script>');
      if (!jsonStr) {
        return callback(new Error('could not find `ytplayer.config`'));
      }

      var jstream = new JStream();
      var ended = false;
      jstream.on('data', function(config) {
        ended = true;
        jstream.pause();

        var newFormats = util.parseFormats(config.args);
        var html5playerfile = 'http:' + config.assets.js;
        crequest(html5playerfile, function(err, body) {
          if (err) return callback(err);

          var tokens = exports.extractActions(body);
          if (!tokens || !tokens.length) {
            if (debug) {
              var splits = html5playerfile.split('/');
              var name = splits[splits.length - 2].slice(12);
              var filename = name + '.js';
              var filepath = path.resolve(
                __dirname, '../test/files/html5player/' + filename);
              fs.writeFile(filepath, body);
              var html5player = require('../test/html5player.json');
              if (!html5player[name]) {
                html5player[name] = [];
                fs.writeFile(
                  path.resolve(__dirname, '../test/html5player.json'),
                  JSON.stringify(html5player, null, 2));
              }
            }
            callback(
              new Error('could not extract signature deciphering actions'));
            return;
          }

          info.formats = info.formats.map(function(format) {
            var newFormat = newFormats
              .filter(function(f) { return f.itag === format.itag; })[0];
            if (newFormat && newFormat.s) {
              format = newFormat;
            }
            var sig = exports.decipher(tokens, format.s);
            format.url = exports.getDownloadURL(format, sig, debug);
            return format;
          });

          callback(null, info);
        });
      });
      jstream.on('error', function(err) {
        if (ended) { return; }
        callback(
          new Error('could not parse `ytplayer.config`: ' + err.message));
      });
      jstream.end(jsonStr);
    });
Example #3
0
  crequest(requestOptions, function(err, body) {
    if (err) return callback(err);

    var jsonStr = util.between(body, 'ytplayer.config = ', '</script>');
    if (!jsonStr) {
      return callback(new Error('could not find `ytplayer.config`'));
    }

    var jstream = new JStream();
    var ended = false;
    jstream.on('data', function(config) {
      ended = true;
      jstream.pause();
      var info = config.args;

      if (info.status === 'fail') {
        callback(new Error('Error ' + info.errorcode + ': ' + info.reason));
        return;
      }

      // Split some keys by commas.
      KEYS_TO_SPLIT.forEach(function(key) {
        if (!info[key]) return;
        info[key] = info[key]
        .split(',')
        .filter(function(v) { return v !== ''; });
      });

      info.fmt_list = info.fmt_list ?
        info.fmt_list.map(function(format) {
          return format.split('/');
        }) : [];

      if (info.video_verticals) {
        info.video_verticals = info.video_verticals
        .slice(1, -1)
        .split(', ')
        .filter(function(val) { return val !== ''; })
        .map(function(val) { return parseInt(val, 10); })
        ;
      }

      info.formats = util.parseFormats(info);

      var $ = cheerio.load(body);
      info.description = $('#eow-description').text();

      if (downloadURL) {
        sig.get(info, config.assets.js, debug, callback);
      } else {
        callback(null, info);
      }
    });

    jstream.on('error', function(err) {
      if (ended) { return; }
      callback(
        new Error('could not parse `ytplayer.config`: ' + err.message));
    });

    jstream.end(jsonStr);
  });