diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
index 78e5c0b..4d40786 100644
--- a/node_modules/.package-lock.json
+++ b/node_modules/.package-lock.json
@@ -184,6 +184,18 @@
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
},
+ "node_modules/m3u8stream": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.8.4.tgz",
+ "integrity": "sha512-sco80Db+30RvcaIOndenX6E6oQNgTiBKeJbFPc+yDXwPQIkryfboEbCvXPlBRq3mQTCVPQO93TDVlfRwqpD35w==",
+ "dependencies": {
+ "miniget": "^4.0.0",
+ "sax": "^1.2.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/mime-db": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
@@ -203,6 +215,14 @@
"node": ">= 0.6"
}
},
+ "node_modules/miniget": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/miniget/-/miniget-4.2.1.tgz",
+ "integrity": "sha512-O/DduzDR6f+oDtVype9S/Qu5hhnx73EDYGyZKwU/qN82lehFZdfhoa4DT51SpsO+8epYrB3gcRmws56ROfTIoQ==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/node-fetch": {
"version": "2.6.6",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz",
@@ -233,6 +253,36 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/prism-media": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.2.tgz",
+ "integrity": "sha512-L6UsGHcT6i4wrQhFF1aPK+MNYgjRqR2tUoIqEY+CG1NqVkMjPRKzS37j9f8GiYPlD6wG9ruBj+q5Ax+bH8Ik1g==",
+ "peerDependencies": {
+ "@discordjs/opus": "^0.5.0",
+ "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0",
+ "node-opus": "^0.3.3",
+ "opusscript": "^0.0.8"
+ },
+ "peerDependenciesMeta": {
+ "@discordjs/opus": {
+ "optional": true
+ },
+ "ffmpeg-static": {
+ "optional": true
+ },
+ "node-opus": {
+ "optional": true
+ },
+ "opusscript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ },
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@@ -300,6 +350,34 @@
"optional": true
}
}
+ },
+ "node_modules/ytdl-core": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.9.1.tgz",
+ "integrity": "sha512-6Jbp5RDhUEozlaJQAR+l8oV8AHsx3WUXxSyPxzE6wOIAaLql7Hjiy0ZM58wZoyj1YEenlEPjEqcJIjKYKxvHtQ==",
+ "dependencies": {
+ "m3u8stream": "^0.8.3",
+ "miniget": "^4.0.0",
+ "sax": "^1.1.3"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ytdl-core-discord": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/ytdl-core-discord/-/ytdl-core-discord-1.3.1.tgz",
+ "integrity": "sha512-KW8zYY35jRSkxZTEQtT9EiR2exFwYKhCE8QZbRg5Ge9a0YWDDhBOixSdWb8Cn41B1uHhz8FR15E4E/k0kHNX3w==",
+ "dependencies": {
+ "@types/node": "^15.12.2",
+ "prism-media": "^1.3.1",
+ "ytdl-core": "^4.8.2"
+ }
+ },
+ "node_modules/ytdl-core-discord/node_modules/@types/node": {
+ "version": "15.14.9",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz",
+ "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A=="
}
}
}
diff --git a/node_modules/m3u8stream/LICENSE b/node_modules/m3u8stream/LICENSE
new file mode 100644
index 0000000..00e8ea8
--- /dev/null
+++ b/node_modules/m3u8stream/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (C) 2017 by fent
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/m3u8stream/README.md b/node_modules/m3u8stream/README.md
new file mode 100644
index 0000000..5114c30
--- /dev/null
+++ b/node_modules/m3u8stream/README.md
@@ -0,0 +1,81 @@
+# node-m3u8stream
+
+Reads segments from a [m3u8 playlist][1] or [DASH MPD file][2] into a consumable stream.
+
+[1]: https://tools.ietf.org/html/draft-pantos-http-live-streaming-20
+[2]: https://dashif.org/docs/DASH-IF-IOP-v4.2-clean.pdf
+
+![Depfu](https://img.shields.io/depfu/fent/node-m3u8stream)
+[![codecov](https://codecov.io/gh/fent/node-m3u8stream/branch/master/graph/badge.svg)](https://codecov.io/gh/fent/node-m3u8stream)
+
+
+# Usage
+
+```js
+const fs = require('fs');
+const m3u8stream = require('m3u8stream')
+
+m3u8stream('http://somesite.com/link/to/the/playlist.m3u8')
+ .pipe(fs.createWriteStream('videofile.mp4'));
+```
+
+
+# API
+
+### m3u8stream(url, [options])
+
+Creates a readable stream of binary media data. `options` can have the following
+
+* `begin` - Where to begin playing the video. Accepts an absolute unix timestamp or date and a relative time in the formats `1:23:45.123` and `1m2s`.
+* `liveBuffer` - How much buffer in milliseconds to have for live streams. Default is `20000`.
+* `chunkReadahead` - How many chunks to preload ahead. Default is `3`.
+* `highWaterMark` - How much of the download to buffer into the stream. See [node's docs](https://nodejs.org/api/stream.html#stream_constructor_new_stream_writable_options) for more. Note that the actual amount buffered can be higher since each chunk request maintains its own buffer.
+* `requestOptions` - Any options you want to pass to [miniget](https://github.com/fent/node-miniget), such as `headers`.
+* `parser` - Either "m3u8" or "dash-mpd". Defaults to guessing based on the playlist url ending in `.m3u8` or `.mpd`.
+* `id` - For playlist containing multiple media options. If not given, the first representation will be picked.
+
+### Stream#end()
+
+If called, stops requesting segments, and refreshing the playlist.
+
+#### Event: progress
+* `Object` - Current segment with the following fields,
+ - `number` - num
+ - `number` - size
+ - `number` - duration
+ - `string` - url
+* `number` - Total number of segments.
+* `number` - Bytes downloaded up to this point.
+
+For static non-live playlists, emitted each time a segment has finished downloading. Since total download size is unknown until all segment endpoints are hit, progress is calculated based on how many segments are available.
+
+#### miniget events
+
+All [miniget events](https://github.com/fent/node-miniget#event-redirect) are forwarded and can be listened to from the returned stream.
+
+### m3u8stream.parseTimestamp(time)
+
+Converts human friendly time to milliseconds. Supports the format
+00:00:00.000 for hours, minutes, seconds, and milliseconds respectively.
+And 0ms, 0s, 0m, 0h, and together 1m1s.
+
+* `time` - A string (or number) giving the user-readable input data
+
+### Limitations
+
+Currently, it does not support [encrypted media segments](https://tools.ietf.org/html/draft-pantos-http-live-streaming-20#section-4.3.2.4). This is because the sites where this was tested on and intended for, YouTube and Twitch, don't use it.
+
+This does not parse master playlists, only media playlists. If you want to parse a master playlist to get links to media playlists, you can try the [m3u8 module](https://github.com/tedconf/node-m3u8).
+
+
+# Install
+
+ npm install m3u8stream
+
+
+# Tests
+Tests are written with [mocha](https://mochajs.org)
+
+```bash
+npm test
+```
diff --git a/node_modules/m3u8stream/dist/dash-mpd-parser.d.ts b/node_modules/m3u8stream/dist/dash-mpd-parser.d.ts
new file mode 100644
index 0000000..b3a2bc7
--- /dev/null
+++ b/node_modules/m3u8stream/dist/dash-mpd-parser.d.ts
@@ -0,0 +1,11 @@
+///
+import { Writable } from 'stream';
+import { Parser } from './parser';
+/**
+ * A wrapper around sax that emits segments.
+ */
+export default class DashMPDParser extends Writable implements Parser {
+ private _parser;
+ constructor(targetID?: string);
+ _write(chunk: Buffer, encoding: string, callback: () => void): void;
+}
diff --git a/node_modules/m3u8stream/dist/dash-mpd-parser.js b/node_modules/m3u8stream/dist/dash-mpd-parser.js
new file mode 100644
index 0000000..0fc81f6
--- /dev/null
+++ b/node_modules/m3u8stream/dist/dash-mpd-parser.js
@@ -0,0 +1,183 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const stream_1 = require("stream");
+const sax_1 = __importDefault(require("sax"));
+const parse_time_1 = require("./parse-time");
+/**
+ * A wrapper around sax that emits segments.
+ */
+class DashMPDParser extends stream_1.Writable {
+ constructor(targetID) {
+ super();
+ this._parser = sax_1.default.createStream(false, { lowercase: true });
+ this._parser.on('error', this.destroy.bind(this));
+ let lastTag;
+ let currtime = 0;
+ let seq = 0;
+ let segmentTemplate;
+ let timescale, offset, duration, baseURL;
+ let timeline = [];
+ let getSegments = false;
+ let gotSegments = false;
+ let isStatic;
+ let treeLevel;
+ let periodStart;
+ const tmpl = (str) => {
+ const context = {
+ RepresentationID: targetID,
+ Number: seq,
+ Time: currtime,
+ };
+ return str.replace(/\$(\w+)\$/g, (m, p1) => `${context[p1]}`);
+ };
+ this._parser.on('opentag', node => {
+ switch (node.name) {
+ case 'mpd':
+ currtime =
+ node.attributes.availabilitystarttime ?
+ new Date(node.attributes.availabilitystarttime).getTime() : 0;
+ isStatic = node.attributes.type !== 'dynamic';
+ break;
+ case 'period':
+ // Reset everything on tag.
+ seq = 0;
+ timescale = 1000;
+ duration = 0;
+ offset = 0;
+ baseURL = [];
+ treeLevel = 0;
+ periodStart = parse_time_1.durationStr(node.attributes.start) || 0;
+ break;
+ case 'segmentlist':
+ seq = parseInt(node.attributes.startnumber) || seq;
+ timescale = parseInt(node.attributes.timescale) || timescale;
+ duration = parseInt(node.attributes.duration) || duration;
+ offset = parseInt(node.attributes.presentationtimeoffset) || offset;
+ break;
+ case 'segmenttemplate':
+ segmentTemplate = node.attributes;
+ seq = parseInt(node.attributes.startnumber) || seq;
+ timescale = parseInt(node.attributes.timescale) || timescale;
+ break;
+ case 'segmenttimeline':
+ case 'baseurl':
+ lastTag = node.name;
+ break;
+ case 's':
+ timeline.push({
+ duration: parseInt(node.attributes.d),
+ repeat: parseInt(node.attributes.r),
+ time: parseInt(node.attributes.t),
+ });
+ break;
+ case 'adaptationset':
+ case 'representation':
+ treeLevel++;
+ if (!targetID) {
+ targetID = node.attributes.id;
+ }
+ getSegments = node.attributes.id === `${targetID}`;
+ if (getSegments) {
+ if (periodStart) {
+ currtime += periodStart;
+ }
+ if (offset) {
+ currtime -= offset / timescale * 1000;
+ }
+ this.emit('starttime', currtime);
+ }
+ break;
+ case 'initialization':
+ if (getSegments) {
+ this.emit('item', {
+ url: baseURL.filter(s => !!s).join('') + node.attributes.sourceurl,
+ seq: seq,
+ init: true,
+ duration: 0,
+ });
+ }
+ break;
+ case 'segmenturl':
+ if (getSegments) {
+ gotSegments = true;
+ let tl = timeline.shift();
+ let segmentDuration = ((tl === null || tl === void 0 ? void 0 : tl.duration) || duration) / timescale * 1000;
+ this.emit('item', {
+ url: baseURL.filter(s => !!s).join('') + node.attributes.media,
+ seq: seq++,
+ duration: segmentDuration,
+ });
+ currtime += segmentDuration;
+ }
+ break;
+ }
+ });
+ const onEnd = () => {
+ if (isStatic) {
+ this.emit('endlist');
+ }
+ if (!getSegments) {
+ this.destroy(Error(`Representation '${targetID}' not found`));
+ }
+ else {
+ this.emit('end');
+ }
+ };
+ this._parser.on('closetag', tagName => {
+ switch (tagName) {
+ case 'adaptationset':
+ case 'representation':
+ treeLevel--;
+ if (segmentTemplate && timeline.length) {
+ gotSegments = true;
+ if (segmentTemplate.initialization) {
+ this.emit('item', {
+ url: baseURL.filter(s => !!s).join('') +
+ tmpl(segmentTemplate.initialization),
+ seq: seq,
+ init: true,
+ duration: 0,
+ });
+ }
+ for (let { duration: itemDuration, repeat, time } of timeline) {
+ itemDuration = itemDuration / timescale * 1000;
+ repeat = repeat || 1;
+ currtime = time || currtime;
+ for (let i = 0; i < repeat; i++) {
+ this.emit('item', {
+ url: baseURL.filter(s => !!s).join('') +
+ tmpl(segmentTemplate.media),
+ seq: seq++,
+ duration: itemDuration,
+ });
+ currtime += itemDuration;
+ }
+ }
+ }
+ if (gotSegments) {
+ this.emit('endearly');
+ onEnd();
+ this._parser.removeAllListeners();
+ this.removeAllListeners('finish');
+ }
+ break;
+ }
+ });
+ this._parser.on('text', text => {
+ if (lastTag === 'baseurl') {
+ baseURL[treeLevel] = text;
+ lastTag = null;
+ }
+ });
+ this.on('finish', onEnd);
+ }
+ _write(chunk, encoding, callback) {
+ this._parser.write(chunk, encoding);
+ callback();
+ }
+}
+exports.default = DashMPDParser;
+//# sourceMappingURL=dash-mpd-parser.js.map
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/dash-mpd-parser.js.map b/node_modules/m3u8stream/dist/dash-mpd-parser.js.map
new file mode 100644
index 0000000..24ba878
--- /dev/null
+++ b/node_modules/m3u8stream/dist/dash-mpd-parser.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"dash-mpd-parser.js","sourceRoot":"","sources":["../src/dash-mpd-parser.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/index.d.ts b/node_modules/m3u8stream/dist/index.d.ts
new file mode 100644
index 0000000..7d3ecea
--- /dev/null
+++ b/node_modules/m3u8stream/dist/index.d.ts
@@ -0,0 +1,31 @@
+///
+import { PassThrough } from 'stream';
+import miniget from 'miniget';
+declare namespace m3u8stream {
+ interface Options {
+ begin?: number | string;
+ liveBuffer?: number;
+ chunkReadahead?: number;
+ highWaterMark?: number;
+ requestOptions?: miniget.Options;
+ parser?: 'm3u8' | 'dash-mpd';
+ id?: string;
+ }
+ interface Progress {
+ num: number;
+ size: number;
+ duration: number;
+ url: string;
+ }
+ interface Stream extends PassThrough {
+ end: () => void;
+ on(event: 'progress', progress: Progress, totalSegments: number, downloadedBytes: number): this;
+ on(event: string | symbol, listener: (...args: any) => void): this;
+ }
+ interface m3u8streamFunc {
+ (playlistURL: string, options?: m3u8stream.Options): Stream;
+ parseTimestamp(time: number | string): number;
+ }
+}
+declare let m3u8stream: m3u8stream.m3u8streamFunc;
+export = m3u8stream;
diff --git a/node_modules/m3u8stream/dist/index.js b/node_modules/m3u8stream/dist/index.js
new file mode 100644
index 0000000..f0c1aa8
--- /dev/null
+++ b/node_modules/m3u8stream/dist/index.js
@@ -0,0 +1,182 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+const stream_1 = require("stream");
+const miniget_1 = __importDefault(require("miniget"));
+const m3u8_parser_1 = __importDefault(require("./m3u8-parser"));
+const dash_mpd_parser_1 = __importDefault(require("./dash-mpd-parser"));
+const queue_1 = require("./queue");
+const parse_time_1 = require("./parse-time");
+const supportedParsers = {
+ m3u8: m3u8_parser_1.default,
+ 'dash-mpd': dash_mpd_parser_1.default,
+};
+let m3u8stream = ((playlistURL, options = {}) => {
+ const stream = new stream_1.PassThrough();
+ const chunkReadahead = options.chunkReadahead || 3;
+ // 20 seconds.
+ const liveBuffer = options.liveBuffer || 20000;
+ const requestOptions = options.requestOptions;
+ const Parser = supportedParsers[options.parser || (/\.mpd$/.test(playlistURL) ? 'dash-mpd' : 'm3u8')];
+ if (!Parser) {
+ throw TypeError(`parser '${options.parser}' not supported`);
+ }
+ let begin = 0;
+ if (typeof options.begin !== 'undefined') {
+ begin = typeof options.begin === 'string' ?
+ parse_time_1.humanStr(options.begin) :
+ Math.max(options.begin - liveBuffer, 0);
+ }
+ const forwardEvents = (req) => {
+ for (let event of ['abort', 'request', 'response', 'redirect', 'retry', 'reconnect']) {
+ req.on(event, stream.emit.bind(stream, event));
+ }
+ };
+ let currSegment;
+ const streamQueue = new queue_1.Queue((req, callback) => {
+ currSegment = req;
+ // Count the size manually, since the `content-length` header is not
+ // always there.
+ let size = 0;
+ req.on('data', (chunk) => size += chunk.length);
+ req.pipe(stream, { end: false });
+ req.on('end', () => callback(null, size));
+ }, { concurrency: 1 });
+ let segmentNumber = 0;
+ let downloaded = 0;
+ const requestQueue = new queue_1.Queue((segment, callback) => {
+ let reqOptions = Object.assign({}, requestOptions);
+ if (segment.range) {
+ reqOptions.headers = Object.assign({}, reqOptions.headers, {
+ Range: `bytes=${segment.range.start}-${segment.range.end}`,
+ });
+ }
+ let req = miniget_1.default(new URL(segment.url, playlistURL).toString(), reqOptions);
+ req.on('error', callback);
+ forwardEvents(req);
+ streamQueue.push(req, (_, size) => {
+ downloaded += +size;
+ stream.emit('progress', {
+ num: ++segmentNumber,
+ size: size,
+ duration: segment.duration,
+ url: segment.url,
+ }, requestQueue.total, downloaded);
+ callback(null);
+ });
+ }, { concurrency: chunkReadahead });
+ const onError = (err) => {
+ if (ended) {
+ return;
+ }
+ stream.emit('error', err);
+ // Stop on any error.
+ stream.end();
+ };
+ // When to look for items again.
+ let refreshThreshold;
+ let minRefreshTime;
+ let refreshTimeout;
+ let fetchingPlaylist = true;
+ let ended = false;
+ let isStatic = false;
+ let lastRefresh;
+ const onQueuedEnd = (err) => {
+ currSegment = null;
+ if (err) {
+ onError(err);
+ }
+ else if (!fetchingPlaylist && !ended && !isStatic &&
+ requestQueue.tasks.length + requestQueue.active <= refreshThreshold) {
+ let ms = Math.max(0, minRefreshTime - (Date.now() - lastRefresh));
+ fetchingPlaylist = true;
+ refreshTimeout = setTimeout(refreshPlaylist, ms);
+ }
+ else if ((ended || isStatic) &&
+ !requestQueue.tasks.length && !requestQueue.active) {
+ stream.end();
+ }
+ };
+ let currPlaylist;
+ let lastSeq;
+ let starttime = 0;
+ const refreshPlaylist = () => {
+ lastRefresh = Date.now();
+ currPlaylist = miniget_1.default(playlistURL, requestOptions);
+ currPlaylist.on('error', onError);
+ forwardEvents(currPlaylist);
+ const parser = currPlaylist.pipe(new Parser(options.id));
+ parser.on('starttime', (a) => {
+ if (starttime) {
+ return;
+ }
+ starttime = a;
+ if (typeof options.begin === 'string' && begin >= 0) {
+ begin += starttime;
+ }
+ });
+ parser.on('endlist', () => { isStatic = true; });
+ parser.on('endearly', currPlaylist.unpipe.bind(currPlaylist, parser));
+ let addedItems = [];
+ const addItem = (item) => {
+ if (!item.init) {
+ if (item.seq <= lastSeq) {
+ return;
+ }
+ lastSeq = item.seq;
+ }
+ begin = item.time;
+ requestQueue.push(item, onQueuedEnd);
+ addedItems.push(item);
+ };
+ let tailedItems = [], tailedItemsDuration = 0;
+ parser.on('item', (item) => {
+ let timedItem = Object.assign({ time: starttime }, item);
+ if (begin <= timedItem.time) {
+ addItem(timedItem);
+ }
+ else {
+ tailedItems.push(timedItem);
+ tailedItemsDuration += timedItem.duration;
+ // Only keep the last `liveBuffer` of items.
+ while (tailedItems.length > 1 &&
+ tailedItemsDuration - tailedItems[0].duration > liveBuffer) {
+ const lastItem = tailedItems.shift();
+ tailedItemsDuration -= lastItem.duration;
+ }
+ }
+ starttime += timedItem.duration;
+ });
+ parser.on('end', () => {
+ currPlaylist = null;
+ // If we are too ahead of the stream, make sure to get the
+ // latest available items with a small buffer.
+ if (!addedItems.length && tailedItems.length) {
+ tailedItems.forEach(item => { addItem(item); });
+ }
+ // Refresh the playlist when remaining segments get low.
+ refreshThreshold = Math.max(1, Math.ceil(addedItems.length * 0.01));
+ // Throttle refreshing the playlist by looking at the duration
+ // of live items added on this refresh.
+ minRefreshTime =
+ addedItems.reduce((total, item) => item.duration + total, 0);
+ fetchingPlaylist = false;
+ onQueuedEnd(null);
+ });
+ };
+ refreshPlaylist();
+ stream.end = () => {
+ ended = true;
+ streamQueue.die();
+ requestQueue.die();
+ clearTimeout(refreshTimeout);
+ currPlaylist === null || currPlaylist === void 0 ? void 0 : currPlaylist.destroy();
+ currSegment === null || currSegment === void 0 ? void 0 : currSegment.destroy();
+ stream_1.PassThrough.prototype.end.call(stream, null);
+ };
+ return stream;
+});
+m3u8stream.parseTimestamp = parse_time_1.humanStr;
+module.exports = m3u8stream;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/index.js.map b/node_modules/m3u8stream/dist/index.js.map
new file mode 100644
index 0000000..71385bb
--- /dev/null
+++ b/node_modules/m3u8stream/dist/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/m3u8-parser.d.ts b/node_modules/m3u8stream/dist/m3u8-parser.d.ts
new file mode 100644
index 0000000..d27a18e
--- /dev/null
+++ b/node_modules/m3u8stream/dist/m3u8-parser.d.ts
@@ -0,0 +1,18 @@
+///
+import { Writable } from 'stream';
+import { Parser } from './parser';
+/**
+ * A very simple m3u8 playlist file parser that detects tags and segments.
+ */
+export default class m3u8Parser extends Writable implements Parser {
+ private _lastLine;
+ private _seq;
+ private _nextItemDuration;
+ private _nextItemRange;
+ private _lastItemRangeEnd;
+ constructor();
+ private _parseAttrList;
+ private _parseRange;
+ _parseLine(line: string): void;
+ _write(chunk: Buffer, encoding: string, callback: () => void): void;
+}
diff --git a/node_modules/m3u8stream/dist/m3u8-parser.js b/node_modules/m3u8stream/dist/m3u8-parser.js
new file mode 100644
index 0000000..458b266
--- /dev/null
+++ b/node_modules/m3u8stream/dist/m3u8-parser.js
@@ -0,0 +1,111 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const stream_1 = require("stream");
+/**
+ * A very simple m3u8 playlist file parser that detects tags and segments.
+ */
+class m3u8Parser extends stream_1.Writable {
+ constructor() {
+ super();
+ this._lastLine = '';
+ this._seq = 0;
+ this._nextItemDuration = null;
+ this._nextItemRange = null;
+ this._lastItemRangeEnd = 0;
+ this.on('finish', () => {
+ this._parseLine(this._lastLine);
+ this.emit('end');
+ });
+ }
+ _parseAttrList(value) {
+ let attrs = {};
+ let regex = /([A-Z0-9-]+)=(?:"([^"]*?)"|([^,]*?))/g;
+ let match;
+ while ((match = regex.exec(value)) !== null) {
+ attrs[match[1]] = match[2] || match[3];
+ }
+ return attrs;
+ }
+ _parseRange(value) {
+ if (!value)
+ return null;
+ let svalue = value.split('@');
+ let start = svalue[1] ? parseInt(svalue[1]) : this._lastItemRangeEnd + 1;
+ let end = start + parseInt(svalue[0]) - 1;
+ let range = { start, end };
+ this._lastItemRangeEnd = range.end;
+ return range;
+ }
+ _parseLine(line) {
+ let match = line.match(/^#(EXT[A-Z0-9-]+)(?::(.*))?/);
+ if (match) {
+ // This is a tag.
+ const tag = match[1];
+ const value = match[2] || '';
+ switch (tag) {
+ case 'EXT-X-PROGRAM-DATE-TIME':
+ this.emit('starttime', new Date(value).getTime());
+ break;
+ case 'EXT-X-MEDIA-SEQUENCE':
+ this._seq = parseInt(value);
+ break;
+ case 'EXT-X-MAP': {
+ let attrs = this._parseAttrList(value);
+ if (!attrs.URI) {
+ this.destroy(new Error('`EXT-X-MAP` found without required attribute `URI`'));
+ return;
+ }
+ this.emit('item', {
+ url: attrs.URI,
+ seq: this._seq,
+ init: true,
+ duration: 0,
+ range: this._parseRange(attrs.BYTERANGE),
+ });
+ break;
+ }
+ case 'EXT-X-BYTERANGE': {
+ this._nextItemRange = this._parseRange(value);
+ break;
+ }
+ case 'EXTINF':
+ this._nextItemDuration =
+ Math.round(parseFloat(value.split(',')[0]) * 1000);
+ break;
+ case 'EXT-X-ENDLIST':
+ this.emit('endlist');
+ break;
+ }
+ }
+ else if (!/^#/.test(line) && line.trim()) {
+ // This is a segment
+ this.emit('item', {
+ url: line.trim(),
+ seq: this._seq++,
+ duration: this._nextItemDuration,
+ range: this._nextItemRange,
+ });
+ this._nextItemRange = null;
+ }
+ }
+ _write(chunk, encoding, callback) {
+ let lines = chunk.toString('utf8').split('\n');
+ if (this._lastLine) {
+ lines[0] = this._lastLine + lines[0];
+ }
+ lines.forEach((line, i) => {
+ if (this.destroyed)
+ return;
+ if (i < lines.length - 1) {
+ this._parseLine(line);
+ }
+ else {
+ // Save the last line in case it has been broken up.
+ this._lastLine = line;
+ }
+ });
+ callback();
+ }
+}
+exports.default = m3u8Parser;
+//# sourceMappingURL=m3u8-parser.js.map
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/m3u8-parser.js.map b/node_modules/m3u8stream/dist/m3u8-parser.js.map
new file mode 100644
index 0000000..0bccae1
--- /dev/null
+++ b/node_modules/m3u8stream/dist/m3u8-parser.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"m3u8-parser.js","sourceRoot":"","sources":["../src/m3u8-parser.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/parse-time.d.ts b/node_modules/m3u8stream/dist/parse-time.d.ts
new file mode 100644
index 0000000..d67f296
--- /dev/null
+++ b/node_modules/m3u8stream/dist/parse-time.d.ts
@@ -0,0 +1,16 @@
+/**
+ * Converts human friendly time to milliseconds. Supports the format
+ * 00:00:00.000 for hours, minutes, seconds, and milliseconds respectively.
+ * And 0ms, 0s, 0m, 0h, and together 1m1s.
+ *
+ * @param {number|string} time
+ * @returns {number}
+ */
+export declare const humanStr: (time: number | string) => number;
+/**
+ * Parses a duration string in the form of "123.456S", returns milliseconds.
+ *
+ * @param {string} time
+ * @returns {number}
+ */
+export declare const durationStr: (time: string) => number;
diff --git a/node_modules/m3u8stream/dist/parse-time.js b/node_modules/m3u8stream/dist/parse-time.js
new file mode 100644
index 0000000..011e226
--- /dev/null
+++ b/node_modules/m3u8stream/dist/parse-time.js
@@ -0,0 +1,59 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.durationStr = exports.humanStr = void 0;
+const numberFormat = /^\d+$/;
+const timeFormat = /^(?:(?:(\d+):)?(\d{1,2}):)?(\d{1,2})(?:\.(\d{3}))?$/;
+const timeUnits = {
+ ms: 1,
+ s: 1000,
+ m: 60000,
+ h: 3600000,
+};
+/**
+ * Converts human friendly time to milliseconds. Supports the format
+ * 00:00:00.000 for hours, minutes, seconds, and milliseconds respectively.
+ * And 0ms, 0s, 0m, 0h, and together 1m1s.
+ *
+ * @param {number|string} time
+ * @returns {number}
+ */
+exports.humanStr = (time) => {
+ if (typeof time === 'number') {
+ return time;
+ }
+ if (numberFormat.test(time)) {
+ return +time;
+ }
+ const firstFormat = timeFormat.exec(time);
+ if (firstFormat) {
+ return (+(firstFormat[1] || 0) * timeUnits.h) +
+ (+(firstFormat[2] || 0) * timeUnits.m) +
+ (+firstFormat[3] * timeUnits.s) +
+ +(firstFormat[4] || 0);
+ }
+ else {
+ let total = 0;
+ const r = /(-?\d+)(ms|s|m|h)/g;
+ let rs;
+ while ((rs = r.exec(time)) !== null) {
+ total += +rs[1] * timeUnits[rs[2]];
+ }
+ return total;
+ }
+};
+/**
+ * Parses a duration string in the form of "123.456S", returns milliseconds.
+ *
+ * @param {string} time
+ * @returns {number}
+ */
+exports.durationStr = (time) => {
+ let total = 0;
+ const r = /(\d+(?:\.\d+)?)(S|M|H)/g;
+ let rs;
+ while ((rs = r.exec(time)) !== null) {
+ total += +rs[1] * timeUnits[rs[2].toLowerCase()];
+ }
+ return total;
+};
+//# sourceMappingURL=parse-time.js.map
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/parse-time.js.map b/node_modules/m3u8stream/dist/parse-time.js.map
new file mode 100644
index 0000000..7e97669
--- /dev/null
+++ b/node_modules/m3u8stream/dist/parse-time.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"parse-time.js","sourceRoot":"","sources":["../src/parse-time.ts"],"names":[],"mappings":";;;AAAA,MAAM,YAAY,GAAG,OAAO,CAAC;AAC7B,MAAM,UAAU,GAAG,qDAAqD,CAAC;AACzE,MAAM,SAAS,GAA8B;IAC3C,EAAE,EAAE,CAAC;IACL,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,OAAO;CACX,CAAC;AAEF;;;;;;;GAOG;AACU,QAAA,QAAQ,GAAG,CAAC,IAAqB,EAAU,EAAE;IACxD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QAAE,OAAO,IAAI,CAAC;KAAE;IAC9C,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC;KAAE;IAC9C,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,WAAW,EAAE;QACf,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;YAC3C,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;YACtC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;YAC/B,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;KAC1B;SAAM;QACL,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,CAAC,GAAG,oBAAoB,CAAC;QAC/B,IAAI,EAAE,CAAC;QACP,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE;YACnC,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;SACpC;QACD,OAAO,KAAK,CAAC;KACd;AACH,CAAC,CAAC;AAEF;;;;;GAKG;AACU,QAAA,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE;IAClD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,CAAC,GAAG,yBAAyB,CAAC;IACpC,IAAI,EAA0B,CAAC;IAC/B,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE;QACnC,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;KAClD;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/parser.d.ts b/node_modules/m3u8stream/dist/parser.d.ts
new file mode 100644
index 0000000..ff2ca47
--- /dev/null
+++ b/node_modules/m3u8stream/dist/parser.d.ts
@@ -0,0 +1,19 @@
+///
+import { Writable } from 'stream';
+export interface Item {
+ url: string;
+ seq: number;
+ duration: number;
+ time?: number;
+ range?: {
+ start: number;
+ end: number;
+ };
+ init?: boolean;
+}
+export interface Parser extends Writable {
+ on(event: 'item', listener: (item: Item) => boolean): this;
+ on(event: string | symbol, listener: (...args: any[]) => any): this;
+ emit(event: 'item', item: Item): boolean;
+ emit(event: string, ...args: any[]): boolean;
+}
diff --git a/node_modules/m3u8stream/dist/parser.js b/node_modules/m3u8stream/dist/parser.js
new file mode 100644
index 0000000..a4ed0a7
--- /dev/null
+++ b/node_modules/m3u8stream/dist/parser.js
@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=parser.js.map
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/parser.js.map b/node_modules/m3u8stream/dist/parser.js.map
new file mode 100644
index 0000000..2c52bc6
--- /dev/null
+++ b/node_modules/m3u8stream/dist/parser.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/queue.d.ts b/node_modules/m3u8stream/dist/queue.d.ts
new file mode 100644
index 0000000..b84e3b5
--- /dev/null
+++ b/node_modules/m3u8stream/dist/queue.d.ts
@@ -0,0 +1,39 @@
+export declare type Callback = (err: Error | null, result?: any) => void;
+interface Task {
+ item: T;
+ callback?: Callback;
+}
+declare type Worker = (item: T, cb: Callback) => void;
+export declare class Queue {
+ private _worker;
+ private _concurrency;
+ tasks: Task[];
+ total: number;
+ active: number;
+ /**
+ * A really simple queue with concurrency.
+ *
+ * @param {Function} worker
+ * @param {Object} options
+ * @param {!number} options.concurrency
+ */
+ constructor(worker: Worker, options?: {
+ concurrency?: number;
+ });
+ /**
+ * Push a task to the queue.
+ *
+ * @param {T} item
+ * @param {!Function} callback
+ */
+ push(item: T, callback?: Callback): void;
+ /**
+ * Process next job in queue.
+ */
+ _next(): void;
+ /**
+ * Stops processing queued jobs.
+ */
+ die(): void;
+}
+export {};
diff --git a/node_modules/m3u8stream/dist/queue.js b/node_modules/m3u8stream/dist/queue.js
new file mode 100644
index 0000000..25659a6
--- /dev/null
+++ b/node_modules/m3u8stream/dist/queue.js
@@ -0,0 +1,58 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Queue = void 0;
+class Queue {
+ /**
+ * A really simple queue with concurrency.
+ *
+ * @param {Function} worker
+ * @param {Object} options
+ * @param {!number} options.concurrency
+ */
+ constructor(worker, options = {}) {
+ this._worker = worker;
+ this._concurrency = options.concurrency || 1;
+ this.tasks = [];
+ this.total = 0;
+ this.active = 0;
+ }
+ /**
+ * Push a task to the queue.
+ *
+ * @param {T} item
+ * @param {!Function} callback
+ */
+ push(item, callback) {
+ this.tasks.push({ item, callback });
+ this.total++;
+ this._next();
+ }
+ /**
+ * Process next job in queue.
+ */
+ _next() {
+ if (this.active >= this._concurrency || !this.tasks.length) {
+ return;
+ }
+ const { item, callback } = this.tasks.shift();
+ let callbackCalled = false;
+ this.active++;
+ this._worker(item, (err, result) => {
+ if (callbackCalled) {
+ return;
+ }
+ this.active--;
+ callbackCalled = true;
+ callback === null || callback === void 0 ? void 0 : callback(err, result);
+ this._next();
+ });
+ }
+ /**
+ * Stops processing queued jobs.
+ */
+ die() {
+ this.tasks = [];
+ }
+}
+exports.Queue = Queue;
+//# sourceMappingURL=queue.js.map
\ No newline at end of file
diff --git a/node_modules/m3u8stream/dist/queue.js.map b/node_modules/m3u8stream/dist/queue.js.map
new file mode 100644
index 0000000..1d29d48
--- /dev/null
+++ b/node_modules/m3u8stream/dist/queue.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":";;;AAOA,MAAa,KAAK;IAOhB;;;;;;OAMG;IACH,YAAY,MAAiB,EAAE,UAAoC,EAAE;QACnE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAClB,CAAC;IAGD;;;;;OAKG;IACH,IAAI,CAAC,IAAO,EAAE,QAAmB;QAC/B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAGD;;OAEG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,OAAO;SAAE;QACvE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAa,CAAC;QACzD,IAAI,cAAc,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACjC,IAAI,cAAc,EAAE;gBAAE,OAAO;aAAE;YAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,cAAc,GAAG,IAAI,CAAC;YACtB,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAG,GAAG,EAAE,MAAM,EAAE;YACxB,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAGD;;OAEG;IACH,GAAG;QACD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;IAClB,CAAC;CACF;AA5DD,sBA4DC"}
\ No newline at end of file
diff --git a/node_modules/m3u8stream/package.json b/node_modules/m3u8stream/package.json
new file mode 100644
index 0000000..0e5bb29
--- /dev/null
+++ b/node_modules/m3u8stream/package.json
@@ -0,0 +1,54 @@
+{
+ "name": "m3u8stream",
+ "description": "Reads segments from a m3u8 or dash playlist into a consumable stream.",
+ "keywords": [
+ "m3u8",
+ "hls",
+ "dash",
+ "live",
+ "playlist",
+ "segments",
+ "stream"
+ ],
+ "version": "0.8.4",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/fent/node-m3u8stream.git"
+ },
+ "author": "fent (https://github.com/fent)",
+ "main": "./dist/index.js",
+ "files": [
+ "dist"
+ ],
+ "scripts": {
+ "prepare": "tsc -p tsconfig.build.json",
+ "build": "tsc -p tsconfig.build.json",
+ "test": "nyc --extension .ts --reporter=lcov --reporter=text-summary npm run test:unit",
+ "test:unit": "mocha -- --require ts-node/register test/*-test.ts",
+ "lint": "eslint ./src ./test",
+ "lint:fix": "eslint --fix ./src ./test"
+ },
+ "dependencies": {
+ "miniget": "^4.0.0",
+ "sax": "^1.2.4"
+ },
+ "devDependencies": {
+ "@types/mocha": "^7.0.0",
+ "@types/node": "^13.1.0",
+ "@types/sax": "^1.0.1",
+ "@types/sinon": "^9.0.8",
+ "@typescript-eslint/eslint-plugin": "^4.8.2",
+ "@typescript-eslint/parser": "^4.8.2",
+ "eslint": "^7.14.0",
+ "mocha": "^7.0.1",
+ "nock": "^13.0.5",
+ "nyc": "^15.0.0",
+ "sinon": "^9.2.0",
+ "ts-node": "^9.0.0",
+ "typescript": "^4.0.5"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "license": "MIT"
+}
diff --git a/node_modules/miniget/LICENSE b/node_modules/miniget/LICENSE
new file mode 100644
index 0000000..00e8ea8
--- /dev/null
+++ b/node_modules/miniget/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (C) 2017 by fent
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/miniget/README.md b/node_modules/miniget/README.md
new file mode 100644
index 0000000..25ed8af
--- /dev/null
+++ b/node_modules/miniget/README.md
@@ -0,0 +1,111 @@
+# node-miniget
+
+A small http(s) GET library with redirects, retries, reconnects, concatenating or streaming, and no dependencies. This keeps filesize small for potential browser use.
+
+![Depfu](https://img.shields.io/depfu/fent/node-miniget)
+[![codecov](https://codecov.io/gh/fent/node-miniget/branch/master/graph/badge.svg)](https://codecov.io/gh/fent/node-miniget)
+
+
+# Usage
+
+Concatenates a response
+
+```js
+const miniget = require('miniget');
+
+miniget('http://mywebsite.com', (err, res, body) => {
+ console.log('webpage contents: ', body);
+});
+
+// with await
+let body = await miniget('http://yourwebsite.com').text();
+```
+
+Request can be streamed right away
+
+```js
+miniget('http://api.mywebsite.com/v1/messages.json')
+ .pipe(someWritableStream());
+```
+
+
+# API
+
+### miniget(url, [options])
+
+Makes a GET request. `url` can be a string or a `URL` object. `options` can have any properties from the [`http.request()` function](https://nodejs.org/api/http.html#http_http_request_options_callback), in addition to
+
+* `maxRedirects` - Default is `10`.
+* `maxRetries` - Number of times to retry the request if there is a 500 or connection error. Default is `2`.
+* `maxReconnects` - During a big download, if there is a disconnect, miniget can try to reconnect and continue the download where it left off. Default is `0`.
+* `backoff` - An object with `inc` and `max` used to calculate how long to wait to retry a request. Default is `{ inc: 100, max: 10000 }`.
+* `highWaterMark` - Amount of data to buffer when in stream mode.
+* `transform` - Use this to add additional features. Called with the object that `http.get()` or `https.get()` would be called with. Must return a transformed object.
+* `acceptEncoding` - An object with encoding name as the key, and the value as a function that returns a decoding stream.
+ ```js
+ acceptEncoding: { gzip: () => require('zlip').createGunzip(stream) }
+ ```
+ Given encodings will be added to the `Accept-Encoding` header, and the response will be decoded if the server responds with encoded content.
+
+Defaults are held in `miniget.defaultOptions` and can be adjusted globally.
+
+Miniget returns a readable stream, errors will then be emitted on the stream. Returned stream has additional methods added, and can emit the following events.
+
+### Stream#destroy([error])
+
+Destroys the request.
+
+### Stream#destroyed
+
+Set to `true` after `Stream#destroy()` has been called.
+
+### Stream#text()
+
+Returns a promise that resolves to the concatenated contents of the response.
+
+```js
+let body = await miniget('http://yourwebsite.com').text();
+```
+
+#### Event: redirect
+* `string` - URL redirected to.
+
+Emitted when the request was redirected with a redirection status code.
+
+#### Event: retry
+* `number` - Number of retry.
+* `Error` - Request or status code error.
+
+Emitted when the request fails, or the response has a status code >= 500.
+
+#### Event: reconnect
+* `number` - Number of reconnect.
+* `Error` - Request or response error.
+
+Emitted when the request or response fails after download has started.
+
+#### Event: request
+* [`http.ClientRequest`](https://nodejs.org/api/http.html#http_class_http_clientrequest) - Request.
+
+Emitted when a video request is made, including after any redirects, retries, and reconnects.
+
+#### Event: response
+* [`http.ServerResponse`](https://nodejs.org/api/http.html#http_class_http_serverresponse) - Response.
+
+Emitted when a video response has been found and has started downloading, including after any successful reconnects.
+
+#### Forwarded events
+
+Any events emitted from the [request](https://nodejs.org/api/http.html#http_class_http_clientrequest) or [response](https://nodejs.org/api/http.html#http_class_http_serverresponse) objects will be forwarded to the miniget stream.
+
+# Install
+
+ npm install miniget
+
+
+# Tests
+Tests are written with [mocha](https://mochajs.org)
+
+```bash
+npm test
+```
diff --git a/node_modules/miniget/dist/index.d.ts b/node_modules/miniget/dist/index.d.ts
new file mode 100644
index 0000000..0847c0d
--- /dev/null
+++ b/node_modules/miniget/dist/index.d.ts
@@ -0,0 +1,65 @@
+///
+import { RequestOptions } from 'http';
+import { PassThrough, Transform } from 'stream';
+declare namespace Miniget {
+ interface Options extends RequestOptions {
+ maxRedirects?: number;
+ maxRetries?: number;
+ maxReconnects?: number;
+ backoff?: {
+ inc: number;
+ max: number;
+ };
+ highWaterMark?: number;
+ transform?: (parsedUrl: RequestOptions) => RequestOptions;
+ acceptEncoding?: {
+ [key: string]: () => Transform;
+ };
+ }
+ interface DefaultOptions extends Options {
+ maxRedirects: number;
+ maxRetries: number;
+ maxReconnects: number;
+ backoff: {
+ inc: number;
+ max: number;
+ };
+ }
+ type defaultOptions = Miniget.Options;
+ type MinigetError = Error;
+ interface Stream extends PassThrough {
+ abort: (err?: Error) => void;
+ aborted: boolean;
+ destroy: (err?: Error) => void;
+ destroyed: boolean;
+ text: () => Promise;
+ on(event: 'reconnect', listener: (attempt: number, err?: Miniget.MinigetError) => void): this;
+ on(event: 'retry', listener: (attempt: number, err?: Miniget.MinigetError) => void): this;
+ on(event: 'redirect', listener: (url: string) => void): this;
+ on(event: string | symbol, listener: (...args: any) => void): this;
+ }
+}
+declare function Miniget(url: string | URL, options?: Miniget.Options): Miniget.Stream;
+declare namespace Miniget {
+ var defaultOptions: {
+ maxRedirects: number;
+ maxRetries: number;
+ maxReconnects: number;
+ backoff: {
+ inc: number;
+ max: number;
+ };
+ };
+ var MinigetError: {
+ new (message: string, statusCode?: number | undefined): {
+ statusCode?: number | undefined;
+ name: string;
+ message: string;
+ stack?: string | undefined;
+ };
+ captureStackTrace(targetObject: object, constructorOpt?: Function | undefined): void;
+ prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined;
+ stackTraceLimit: number;
+ };
+}
+export = Miniget;
diff --git a/node_modules/miniget/dist/index.js b/node_modules/miniget/dist/index.js
new file mode 100644
index 0000000..b1da727
--- /dev/null
+++ b/node_modules/miniget/dist/index.js
@@ -0,0 +1,285 @@
+"use strict";
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+const http_1 = __importDefault(require("http"));
+const https_1 = __importDefault(require("https"));
+const stream_1 = require("stream");
+const httpLibs = { 'http:': http_1.default, 'https:': https_1.default };
+const redirectStatusCodes = new Set([301, 302, 303, 307, 308]);
+const retryStatusCodes = new Set([429, 503]);
+// `request`, `response`, `abort`, left out, miniget will emit these.
+const requestEvents = ['connect', 'continue', 'information', 'socket', 'timeout', 'upgrade'];
+const responseEvents = ['aborted'];
+Miniget.MinigetError = class MinigetError extends Error {
+ constructor(message, statusCode) {
+ super(message);
+ this.statusCode = statusCode;
+ }
+};
+Miniget.defaultOptions = {
+ maxRedirects: 10,
+ maxRetries: 2,
+ maxReconnects: 0,
+ backoff: { inc: 100, max: 10000 },
+};
+function Miniget(url, options = {}) {
+ var _a;
+ const opts = Object.assign({}, Miniget.defaultOptions, options);
+ const stream = new stream_1.PassThrough({ highWaterMark: opts.highWaterMark });
+ stream.destroyed = stream.aborted = false;
+ let activeRequest;
+ let activeResponse;
+ let activeDecodedStream;
+ let redirects = 0;
+ let retries = 0;
+ let retryTimeout;
+ let reconnects = 0;
+ let contentLength;
+ let acceptRanges = false;
+ let rangeStart = 0, rangeEnd;
+ let downloaded = 0;
+ // Check if this is a ranged request.
+ if ((_a = opts.headers) === null || _a === void 0 ? void 0 : _a.Range) {
+ let r = /bytes=(\d+)-(\d+)?/.exec(`${opts.headers.Range}`);
+ if (r) {
+ rangeStart = parseInt(r[1], 10);
+ rangeEnd = parseInt(r[2], 10);
+ }
+ }
+ // Add `Accept-Encoding` header.
+ if (opts.acceptEncoding) {
+ opts.headers = Object.assign({
+ 'Accept-Encoding': Object.keys(opts.acceptEncoding).join(', '),
+ }, opts.headers);
+ }
+ const downloadHasStarted = () => activeDecodedStream && downloaded > 0;
+ const downloadComplete = () => !acceptRanges || downloaded === contentLength;
+ const reconnect = (err) => {
+ activeDecodedStream = null;
+ retries = 0;
+ let inc = opts.backoff.inc;
+ let ms = Math.min(inc, opts.backoff.max);
+ retryTimeout = setTimeout(doDownload, ms);
+ stream.emit('reconnect', reconnects, err);
+ };
+ const reconnectIfEndedEarly = (err) => {
+ if (options.method !== 'HEAD' && !downloadComplete() && reconnects++ < opts.maxReconnects) {
+ reconnect(err);
+ return true;
+ }
+ return false;
+ };
+ const retryRequest = (retryOptions) => {
+ if (stream.destroyed) {
+ return false;
+ }
+ if (downloadHasStarted()) {
+ return reconnectIfEndedEarly(retryOptions.err);
+ }
+ else if ((!retryOptions.err || retryOptions.err.message === 'ENOTFOUND') &&
+ retries++ < opts.maxRetries) {
+ let ms = retryOptions.retryAfter ||
+ Math.min(retries * opts.backoff.inc, opts.backoff.max);
+ retryTimeout = setTimeout(doDownload, ms);
+ stream.emit('retry', retries, retryOptions.err);
+ return true;
+ }
+ return false;
+ };
+ const forwardEvents = (ee, events) => {
+ for (let event of events) {
+ ee.on(event, stream.emit.bind(stream, event));
+ }
+ };
+ const doDownload = () => {
+ let parsed = {}, httpLib;
+ try {
+ let urlObj = typeof url === 'string' ? new URL(url) : url;
+ parsed = Object.assign({}, {
+ host: urlObj.host,
+ hostname: urlObj.hostname,
+ path: urlObj.pathname + urlObj.search + urlObj.hash,
+ port: urlObj.port,
+ protocol: urlObj.protocol,
+ });
+ if (urlObj.username) {
+ parsed.auth = `${urlObj.username}:${urlObj.password}`;
+ }
+ httpLib = httpLibs[String(parsed.protocol)];
+ }
+ catch (err) {
+ // Let the error be caught by the if statement below.
+ }
+ if (!httpLib) {
+ stream.emit('error', new Miniget.MinigetError(`Invalid URL: ${url}`));
+ return;
+ }
+ Object.assign(parsed, opts);
+ if (acceptRanges && downloaded > 0) {
+ let start = downloaded + rangeStart;
+ let end = rangeEnd || '';
+ parsed.headers = Object.assign({}, parsed.headers, {
+ Range: `bytes=${start}-${end}`,
+ });
+ }
+ if (opts.transform) {
+ try {
+ parsed = opts.transform(parsed);
+ }
+ catch (err) {
+ stream.emit('error', err);
+ return;
+ }
+ if (!parsed || parsed.protocol) {
+ httpLib = httpLibs[String(parsed === null || parsed === void 0 ? void 0 : parsed.protocol)];
+ if (!httpLib) {
+ stream.emit('error', new Miniget.MinigetError('Invalid URL object from `transform` function'));
+ return;
+ }
+ }
+ }
+ const onError = (err) => {
+ if (stream.destroyed || stream.readableEnded) {
+ return;
+ }
+ // Needed for node v10.
+ if (stream._readableState.ended) {
+ return;
+ }
+ cleanup();
+ if (!retryRequest({ err })) {
+ stream.emit('error', err);
+ }
+ else {
+ activeRequest.removeListener('close', onRequestClose);
+ }
+ };
+ const onRequestClose = () => {
+ cleanup();
+ retryRequest({});
+ };
+ const cleanup = () => {
+ activeRequest.removeListener('close', onRequestClose);
+ activeResponse === null || activeResponse === void 0 ? void 0 : activeResponse.removeListener('data', onData);
+ activeDecodedStream === null || activeDecodedStream === void 0 ? void 0 : activeDecodedStream.removeListener('end', onEnd);
+ };
+ const onData = (chunk) => { downloaded += chunk.length; };
+ const onEnd = () => {
+ cleanup();
+ if (!reconnectIfEndedEarly()) {
+ stream.end();
+ }
+ };
+ activeRequest = httpLib.request(parsed, (res) => {
+ // Needed for node v10, v12.
+ // istanbul ignore next
+ if (stream.destroyed) {
+ return;
+ }
+ if (redirectStatusCodes.has(res.statusCode)) {
+ if (redirects++ >= opts.maxRedirects) {
+ stream.emit('error', new Miniget.MinigetError('Too many redirects'));
+ }
+ else {
+ if (res.headers.location) {
+ url = res.headers.location;
+ }
+ else {
+ let err = new Miniget.MinigetError('Redirect status code given with no location', res.statusCode);
+ stream.emit('error', err);
+ cleanup();
+ return;
+ }
+ setTimeout(doDownload, parseInt(res.headers['retry-after'] || '0', 10) * 1000);
+ stream.emit('redirect', url);
+ }
+ cleanup();
+ return;
+ // Check for rate limiting.
+ }
+ else if (retryStatusCodes.has(res.statusCode)) {
+ if (!retryRequest({ retryAfter: parseInt(res.headers['retry-after'] || '0', 10) })) {
+ let err = new Miniget.MinigetError(`Status code: ${res.statusCode}`, res.statusCode);
+ stream.emit('error', err);
+ }
+ cleanup();
+ return;
+ }
+ else if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 400)) {
+ let err = new Miniget.MinigetError(`Status code: ${res.statusCode}`, res.statusCode);
+ if (res.statusCode >= 500) {
+ onError(err);
+ }
+ else {
+ stream.emit('error', err);
+ }
+ cleanup();
+ return;
+ }
+ activeDecodedStream = res;
+ if (opts.acceptEncoding && res.headers['content-encoding']) {
+ for (let enc of res.headers['content-encoding'].split(', ').reverse()) {
+ let fn = opts.acceptEncoding[enc];
+ if (fn) {
+ activeDecodedStream = activeDecodedStream.pipe(fn());
+ activeDecodedStream.on('error', onError);
+ }
+ }
+ }
+ if (!contentLength) {
+ contentLength = parseInt(`${res.headers['content-length']}`, 10);
+ acceptRanges = res.headers['accept-ranges'] === 'bytes' &&
+ contentLength > 0 && opts.maxReconnects > 0;
+ }
+ res.on('data', onData);
+ activeDecodedStream.on('end', onEnd);
+ activeDecodedStream.pipe(stream, { end: !acceptRanges });
+ activeResponse = res;
+ stream.emit('response', res);
+ res.on('error', onError);
+ forwardEvents(res, responseEvents);
+ });
+ activeRequest.on('error', onError);
+ activeRequest.on('close', onRequestClose);
+ forwardEvents(activeRequest, requestEvents);
+ if (stream.destroyed) {
+ streamDestroy(...destroyArgs);
+ }
+ stream.emit('request', activeRequest);
+ activeRequest.end();
+ };
+ stream.abort = (err) => {
+ console.warn('`MinigetStream#abort()` has been deprecated in favor of `MinigetStream#destroy()`');
+ stream.aborted = true;
+ stream.emit('abort');
+ stream.destroy(err);
+ };
+ let destroyArgs;
+ const streamDestroy = (err) => {
+ activeRequest.destroy(err);
+ activeDecodedStream === null || activeDecodedStream === void 0 ? void 0 : activeDecodedStream.unpipe(stream);
+ activeDecodedStream === null || activeDecodedStream === void 0 ? void 0 : activeDecodedStream.destroy();
+ clearTimeout(retryTimeout);
+ };
+ stream._destroy = (...args) => {
+ stream.destroyed = true;
+ if (activeRequest) {
+ streamDestroy(...args);
+ }
+ else {
+ destroyArgs = args;
+ }
+ };
+ stream.text = () => new Promise((resolve, reject) => {
+ let body = '';
+ stream.setEncoding('utf8');
+ stream.on('data', chunk => body += chunk);
+ stream.on('end', () => resolve(body));
+ stream.on('error', reject);
+ });
+ process.nextTick(doDownload);
+ return stream;
+}
+module.exports = Miniget;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/node_modules/miniget/dist/index.js.map b/node_modules/miniget/dist/index.js.map
new file mode 100644
index 0000000..34bc626
--- /dev/null
+++ b/node_modules/miniget/dist/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/node_modules/miniget/package.json b/node_modules/miniget/package.json
new file mode 100644
index 0000000..25b119f
--- /dev/null
+++ b/node_modules/miniget/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "miniget",
+ "description": "A small HTTP(S) GET request library, with redirects and streaming.",
+ "keywords": [
+ "request",
+ "http",
+ "https",
+ "redirect",
+ "stream"
+ ],
+ "version": "4.2.1",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/fent/node-miniget.git"
+ },
+ "author": "fent (https://github.com/fent)",
+ "main": "./dist/index.js",
+ "files": [
+ "dist"
+ ],
+ "scripts": {
+ "prepare": "tsc -p tsconfig.build.json",
+ "build": "tsc -p tsconfig.build.json",
+ "test": "nyc --extension .ts --reporter=lcov --reporter=text-summary npm run test:unit",
+ "test:unit": "mocha -- --require ts-node/register test/*-test.ts",
+ "lint": "eslint ./src ./test",
+ "lint:fix": "eslint --fix ./src ./test"
+ },
+ "dependencies": {},
+ "devDependencies": {
+ "@types/mocha": "^7.0.0",
+ "@types/node": "^14.14.9",
+ "@types/sinon": "^9.0.8",
+ "@typescript-eslint/eslint-plugin": "^4.8.2",
+ "@typescript-eslint/parser": "^4.8.2",
+ "eslint": "^7.14.0",
+ "longjohn": "^0.2.12",
+ "mocha": "^7.0.1",
+ "nock": "^13.0.4",
+ "nyc": "^15.0.0",
+ "sinon": "^9.2.0",
+ "stream-equal": "^1.1.1",
+ "ts-node": "^8.10.1",
+ "typescript": "^3.9.7"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "license": "MIT"
+}
diff --git a/node_modules/prism-media/LICENSE b/node_modules/prism-media/LICENSE
new file mode 100644
index 0000000..369db8d
--- /dev/null
+++ b/node_modules/prism-media/LICENSE
@@ -0,0 +1,190 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ Copyright 2019 - 2020 Amish Shah
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/node_modules/prism-media/README.md b/node_modules/prism-media/README.md
new file mode 100644
index 0000000..59488db
--- /dev/null
+++ b/node_modules/prism-media/README.md
@@ -0,0 +1,69 @@
+[![Logo](https://hydrabolt.me/assets/prism-media-logo.svg)](https://amishshah.github.io/prism-media/)
+
+
+
+## What is it?
+
+An easy-to-use stream-based toolkit that you can use for media processing. All the features provided have predictable
+abstractions and join together coherently.
+
+```js
+// This example will demux and decode an Opus-containing OGG file, and then write it to a file.
+const prism = require('prism-media');
+const fs = require('fs');
+
+fs.createReadStream('./audio.ogg')
+ .pipe(new prism.opus.OggDemuxer())
+ .pipe(new prism.opus.Decoder({ rate: 48000, channels: 2, frameSize: 960 }))
+ .pipe(fs.createWriteStream('./audio.pcm'));
+```
+
+The example above can work with either a native or pure JavaScript Opus decoder - you don't need to worry about changing
+your code for whichever you install.
+
+- FFmpeg support (either through npm modules or a normal installation)
+- Opus support (native or pure JavaScript)
+- Demuxing for WebM/OGG files (no modules required!)
+- Volume Altering (no modules required!)
+
+## Dependencies
+
+The following dependencies are all optional, and you should only install one from each category (the first listed in
+each category is preferred)
+
+- Opus
+ - [`@discordjs/opus`](https://github.com/discordjs/opus)
+ - [`node-opus`](https://github.com/Rantanen/node-opus)
+ - [`opusscript`](https://github.com/abalabahaha/opusscript)
+- FFmpeg
+ - [`ffmpeg-static`](http://npmjs.com/ffmpeg-static)
+ - `ffmpeg` from a [normal installation](https://www.ffmpeg.org/download.html)
+
+## Useful Links
+
+- [Documentation](https://amishshah.github.io/prism-media)
+- [Examples](https://github.com/amishshah/prism-media/tree/master/examples)
+- [Patreon](https://www.patreon.com/discordjs)
+
+## License
+
+> Copyright 2019 - 2020 Amish Shah
+>
+> Licensed under the Apache License, Version 2.0 (the "License");
+> you may not use this file except in compliance with the License.
+> You may obtain a copy of the License at
+>
+> http://www.apache.org/licenses/LICENSE-2.0
+>
+> Unless required by applicable law or agreed to in writing, software
+> distributed under the License is distributed on an "AS IS" BASIS,
+> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+> See the License for the specific language governing permissions and
+> limitations under the License.
\ No newline at end of file
diff --git a/node_modules/prism-media/package.json b/node_modules/prism-media/package.json
new file mode 100644
index 0000000..17ae3e5
--- /dev/null
+++ b/node_modules/prism-media/package.json
@@ -0,0 +1,63 @@
+{
+ "name": "prism-media",
+ "version": "1.3.2",
+ "description": "Easy-to-use stream-based media transcoding",
+ "main": "src/index.js",
+ "types": "typings/index.d.ts",
+ "scripts": {
+ "lint": "eslint src",
+ "test": "npm run lint && jest && npm run docs",
+ "docs": "docma"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/hydrabolt/prism-media.git"
+ },
+ "keywords": [
+ "audio",
+ "media",
+ "ffmpeg",
+ "opus",
+ "pcm",
+ "webm",
+ "ogg"
+ ],
+ "author": "Amish Shah ",
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/hydrabolt/prism-media/issues"
+ },
+ "homepage": "https://github.com/hydrabolt/prism-media#readme",
+ "devDependencies": {
+ "docma": "^3.2.2",
+ "eslint": "^7.32.0",
+ "jest": "^27.0.6"
+ },
+ "jest": {
+ "testURL": "http://localhost/"
+ },
+ "peerDependencies": {
+ "@discordjs/opus": "^0.5.0",
+ "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0",
+ "node-opus": "^0.3.3",
+ "opusscript": "^0.0.8"
+ },
+ "peerDependenciesMeta": {
+ "@discordjs/opus": {
+ "optional": true
+ },
+ "node-opus": {
+ "optional": true
+ },
+ "opusscript": {
+ "optional": true
+ },
+ "ffmpeg-static": {
+ "optional": true
+ }
+ },
+ "files": [
+ "src/",
+ "typings/"
+ ]
+}
diff --git a/node_modules/prism-media/src/core/FFmpeg.js b/node_modules/prism-media/src/core/FFmpeg.js
new file mode 100644
index 0000000..a1d9215
--- /dev/null
+++ b/node_modules/prism-media/src/core/FFmpeg.js
@@ -0,0 +1,160 @@
+const ChildProcess = require('child_process');
+const { Duplex } = require('stream');
+
+let FFMPEG = {
+ command: null,
+ output: null,
+};
+
+const VERSION_REGEX = /version (.+) Copyright/mi;
+
+Object.defineProperty(FFMPEG, 'version', {
+ get() {
+ return VERSION_REGEX.exec(FFMPEG.output)[1];
+ },
+ enumerable: true,
+});
+
+/**
+ * An FFmpeg transform stream that provides an interface to FFmpeg.
+ * @memberof core
+ */
+class FFmpeg extends Duplex {
+ /**
+ * Creates a new FFmpeg transform stream
+ * @memberof core
+ * @param {Object} options Options you would pass to a regular Transform stream, plus an `args` option
+ * @param {Array} options.args Arguments to pass to FFmpeg
+ * @param {boolean} [options.shell=false] Whether FFmpeg should be spawned inside a shell
+ * @example
+ * // By default, if you don't specify an input (`-i ...`) prism will assume you're piping a stream into it.
+ * const transcoder = new prism.FFmpeg({
+ * args: [
+ * '-analyzeduration', '0',
+ * '-loglevel', '0',
+ * '-f', 's16le',
+ * '-ar', '48000',
+ * '-ac', '2',
+ * ]
+ * });
+ * const s16le = mp3File.pipe(transcoder);
+ * const opus = s16le.pipe(new prism.opus.Encoder({ rate: 48000, channels: 2, frameSize: 960 }));
+ */
+ constructor(options = {}) {
+ super();
+ this.process = FFmpeg.create({ shell: false, ...options });
+ const EVENTS = {
+ readable: this._reader,
+ data: this._reader,
+ end: this._reader,
+ unpipe: this._reader,
+ finish: this._writer,
+ drain: this._writer,
+ };
+
+ this._readableState = this._reader._readableState;
+ this._writableState = this._writer._writableState;
+
+ this._copy(['write', 'end'], this._writer);
+ this._copy(['read', 'setEncoding', 'pipe', 'unpipe'], this._reader);
+
+ for (const method of ['on', 'once', 'removeListener', 'removeListeners', 'listeners']) {
+ this[method] = (ev, fn) => EVENTS[ev] ? EVENTS[ev][method](ev, fn) : Duplex.prototype[method].call(this, ev, fn);
+ }
+
+ const processError = error => this.emit('error', error);
+ this._reader.on('error', processError);
+ this._writer.on('error', processError);
+ }
+
+ get _reader() { return this.process.stdout; }
+ get _writer() { return this.process.stdin; }
+
+ _copy(methods, target) {
+ for (const method of methods) {
+ this[method] = target[method].bind(target);
+ }
+ }
+
+ _destroy(err, cb) {
+ this._cleanup();
+ return cb ? cb(err) : undefined;
+ }
+
+ _final(cb) {
+ this._cleanup();
+ cb();
+ }
+
+ _cleanup() {
+ if (this.process) {
+ this.once('error', () => {});
+ this.process.kill('SIGKILL');
+ this.process = null;
+ }
+ }
+
+
+ /**
+ * The available FFmpeg information
+ * @typedef {Object} FFmpegInfo
+ * @memberof core
+ * @property {string} command The command used to launch FFmpeg
+ * @property {string} output The output from running `ffmpeg -h`
+ * @property {string} version The version of FFmpeg being used, determined from `output`.
+ */
+
+ /**
+ * Finds a suitable FFmpeg command and obtains the debug information from it.
+ * @param {boolean} [force=false] If true, will ignore any cached results and search for the command again
+ * @returns {FFmpegInfo}
+ * @throws Will throw an error if FFmpeg cannot be found.
+ * @example
+ * const ffmpeg = prism.FFmpeg.getInfo();
+ *
+ * console.log(`Using FFmpeg version ${ffmpeg.version}`);
+ *
+ * if (ffmpeg.output.includes('--enable-libopus')) {
+ * console.log('libopus is available!');
+ * } else {
+ * console.log('libopus is unavailable!');
+ * }
+ */
+ static getInfo(force = false) {
+ if (FFMPEG.command && !force) return FFMPEG;
+ const sources = [() => {
+ const ffmpegStatic = require('ffmpeg-static');
+ return ffmpegStatic.path || ffmpegStatic;
+ }, 'ffmpeg', 'avconv', './ffmpeg', './avconv'];
+ for (let source of sources) {
+ try {
+ if (typeof source === 'function') source = source();
+ const result = ChildProcess.spawnSync(source, ['-h'], { windowsHide: true });
+ if (result.error) throw result.error;
+ Object.assign(FFMPEG, {
+ command: source,
+ output: Buffer.concat(result.output.filter(Boolean)).toString(),
+ });
+ return FFMPEG;
+ } catch (error) {
+ // Do nothing
+ }
+ }
+ throw new Error('FFmpeg/avconv not found!');
+ }
+
+ /**
+ * Creates a new FFmpeg instance. If you do not include `-i ...` it will be assumed that `-i -` should be prepended
+ * to the options and that you'll be piping data into the process.
+ * @param {String[]} [args=[]] Arguments to pass to FFmpeg
+ * @returns {ChildProcess}
+ * @private
+ * @throws Will throw an error if FFmpeg cannot be found.
+ */
+ static create({ args = [], shell = false } = {}) {
+ if (!args.includes('-i')) args.unshift('-i', '-');
+ return ChildProcess.spawn(FFmpeg.getInfo().command, args.concat(['pipe:1']), { windowsHide: true, shell });
+ }
+}
+
+module.exports = FFmpeg;
diff --git a/node_modules/prism-media/src/core/VolumeTransformer.js b/node_modules/prism-media/src/core/VolumeTransformer.js
new file mode 100644
index 0000000..782f8de
--- /dev/null
+++ b/node_modules/prism-media/src/core/VolumeTransformer.js
@@ -0,0 +1,128 @@
+// Based on discord.js' old volume system
+
+const { Transform } = require('stream');
+
+/**
+ * Transforms a stream of PCM volume.
+ * @memberof core
+ * @extends TransformStream
+ */
+class VolumeTransformer extends Transform {
+ /**
+ * @memberof core
+ * @param {Object} options Any optional TransformStream options plus some extra:
+ * @param {string} options.type The type of transformer: s16le (signed 16-bit little-endian), s16be, s32le, s32be
+ * @param {number} [options.volume=1] The output volume of the stream
+ * @example
+ * // Half the volume of a signed 16-bit little-endian PCM stream
+ * input
+ * .pipe(new prism.VolumeTransformer({ type: 's16le', volume: 0.5 }))
+ * .pipe(writeStream);
+ */
+ constructor(options = {}) {
+ super(options);
+ switch (options.type) {
+ case 's16le':
+ this._readInt = (buffer, index) => buffer.readInt16LE(index);
+ this._writeInt = (buffer, int, index) => buffer.writeInt16LE(int, index);
+ this._bits = 16;
+ break;
+ case 's16be':
+ this._readInt = (buffer, index) => buffer.readInt16BE(index);
+ this._writeInt = (buffer, int, index) => buffer.writeInt16BE(int, index);
+ this._bits = 16;
+ break;
+ case 's32le':
+ this._readInt = (buffer, index) => buffer.readInt32LE(index);
+ this._writeInt = (buffer, int, index) => buffer.writeInt32LE(int, index);
+ this._bits = 32;
+ break;
+ case 's32be':
+ this._readInt = (buffer, index) => buffer.readInt32BE(index);
+ this._writeInt = (buffer, int, index) => buffer.writeInt32BE(int, index);
+ this._bits = 32;
+ break;
+ default:
+ throw new Error('VolumeTransformer type should be one of s16le, s16be, s32le, s32be');
+ }
+ this._bytes = this._bits / 8;
+ this._extremum = Math.pow(2, this._bits - 1);
+ this.volume = typeof options.volume === 'undefined' ? 1 : options.volume;
+ this._chunk = Buffer.alloc(0);
+ }
+
+ _readInt(buffer, index) { return index; }
+ _writeInt(buffer, int, index) { return index; }
+
+ _transform(chunk, encoding, done) {
+ // If the volume is 1, act like a passthrough stream
+ if (this.volume === 1) {
+ this.push(chunk);
+ return done();
+ }
+
+ const { _bytes, _extremum } = this;
+
+ chunk = this._chunk = Buffer.concat([this._chunk, chunk]);
+ if (chunk.length < _bytes) return done();
+
+ const complete = Math.floor(chunk.length / _bytes) * _bytes;
+
+ for (let i = 0; i < complete; i += _bytes) {
+ const int = Math.min(_extremum - 1, Math.max(-_extremum, Math.floor(this.volume * this._readInt(chunk, i))));
+ this._writeInt(chunk, int, i);
+ }
+
+ this._chunk = chunk.slice(complete);
+ this.push(chunk.slice(0, complete));
+ return done();
+ }
+
+ _destroy(err, cb) {
+ super._destroy(err, cb);
+ this._chunk = null;
+ }
+
+ /**
+ * Sets the volume relative to the input stream - i.e. 1 is normal, 0.5 is half, 2 is double.
+ * @param {number} volume The volume that you want to set
+ */
+ setVolume(volume) {
+ this.volume = volume;
+ }
+
+ /**
+ * Sets the volume in decibels.
+ * @param {number} db The decibels
+ */
+ setVolumeDecibels(db) {
+ this.setVolume(Math.pow(10, db / 20));
+ }
+
+ /**
+ * Sets the volume so that a perceived value of 0.5 is half the perceived volume etc.
+ * @param {number} value The value for the volume
+ */
+ setVolumeLogarithmic(value) {
+ this.setVolume(Math.pow(value, 1.660964));
+ }
+
+ /**
+ * The current volume of the stream in decibels
+ * @readonly
+ * @type {number}
+ */
+ get volumeDecibels() {
+ return Math.log10(this.volume) * 20;
+ }
+ /**
+ * The current volume of the stream from a logarithmic scale
+ * @readonly
+ * @type {number}
+ */
+ get volumeLogarithmic() {
+ return Math.pow(this.volume, 1 / 1.660964);
+ }
+}
+
+module.exports = VolumeTransformer;
diff --git a/node_modules/prism-media/src/core/WebmBase.js b/node_modules/prism-media/src/core/WebmBase.js
new file mode 100644
index 0000000..75f60f8
--- /dev/null
+++ b/node_modules/prism-media/src/core/WebmBase.js
@@ -0,0 +1,226 @@
+const { Transform } = require('stream');
+
+/**
+ * Base class for WebmOpusDemuxer and WebmVorbisDemuxer.
+ * **You shouldn't directly instantiate this class, use the opus.WebmDemuxer and vorbis.WebmDemuxer
+ * implementations instead!**
+ * @memberof core
+ * @protected
+ * @extends TransformStream
+ */
+class WebmBaseDemuxer extends Transform {
+ /**
+ * Creates a new Webm demuxer.
+ * @private
+ * @memberof core
+ * @param {Object} [options] options that you would pass to a regular Transform stream.
+ */
+ constructor(options = {}) {
+ super(Object.assign({ readableObjectMode: true }, options));
+ this._remainder = null;
+ this._length = 0;
+ this._count = 0;
+ this._skipUntil = null;
+ this._track = null;
+ this._incompleteTrack = {};
+ this._ebmlFound = false;
+ }
+
+ _transform(chunk, encoding, done) {
+ this._length += chunk.length;
+ if (this._remainder) {
+ chunk = Buffer.concat([this._remainder, chunk]);
+ this._remainder = null;
+ }
+ let offset = 0;
+ if (this._skipUntil && this._length > this._skipUntil) {
+ offset = this._skipUntil - this._count;
+ this._skipUntil = null;
+ } else if (this._skipUntil) {
+ this._count += chunk.length;
+ done();
+ return;
+ }
+ let result;
+ while (result !== TOO_SHORT) {
+ try {
+ result = this._readTag(chunk, offset);
+ } catch (error) {
+ done(error);
+ return;
+ }
+ if (result === TOO_SHORT) break;
+ if (result._skipUntil) {
+ this._skipUntil = result._skipUntil;
+ break;
+ }
+ if (result.offset) offset = result.offset;
+ else break;
+ }
+ this._count += offset;
+ this._remainder = chunk.slice(offset);
+ done();
+ return;
+ }
+
+ /**
+ * Reads an EBML ID from a buffer.
+ * @private
+ * @param {Buffer} chunk the buffer to read from.
+ * @param {number} offset the offset in the buffer.
+ * @returns {Object|Symbol} contains an `id` property (buffer) and the new `offset` (number).
+ * Returns the TOO_SHORT symbol if the data wasn't big enough to facilitate the request.
+ */
+ _readEBMLId(chunk, offset) {
+ const idLength = vintLength(chunk, offset);
+ if (idLength === TOO_SHORT) return TOO_SHORT;
+ return {
+ id: chunk.slice(offset, offset + idLength),
+ offset: offset + idLength,
+ };
+ }
+
+ /**
+ * Reads a size variable-integer to calculate the length of the data of a tag.
+ * @private
+ * @param {Buffer} chunk the buffer to read from.
+ * @param {number} offset the offset in the buffer.
+ * @returns {Object|Symbol} contains property `offset` (number), `dataLength` (number) and `sizeLength` (number).
+ * Returns the TOO_SHORT symbol if the data wasn't big enough to facilitate the request.
+ */
+ _readTagDataSize(chunk, offset) {
+ const sizeLength = vintLength(chunk, offset);
+ if (sizeLength === TOO_SHORT) return TOO_SHORT;
+ const dataLength = expandVint(chunk, offset, offset + sizeLength);
+ return { offset: offset + sizeLength, dataLength, sizeLength };
+ }
+
+ /**
+ * Takes a buffer and attempts to read and process a tag.
+ * @private
+ * @param {Buffer} chunk the buffer to read from.
+ * @param {number} offset the offset in the buffer.
+ * @returns {Object|Symbol} contains the new `offset` (number) and optionally the `_skipUntil` property,
+ * indicating that the stream should ignore any data until a certain length is reached.
+ * Returns the TOO_SHORT symbol if the data wasn't big enough to facilitate the request.
+ */
+ _readTag(chunk, offset) {
+ const idData = this._readEBMLId(chunk, offset);
+ if (idData === TOO_SHORT) return TOO_SHORT;
+ const ebmlID = idData.id.toString('hex');
+ if (!this._ebmlFound) {
+ if (ebmlID === '1a45dfa3') this._ebmlFound = true;
+ else throw Error('Did not find the EBML tag at the start of the stream');
+ }
+ offset = idData.offset;
+ const sizeData = this._readTagDataSize(chunk, offset);
+ if (sizeData === TOO_SHORT) return TOO_SHORT;
+ const { dataLength } = sizeData;
+ offset = sizeData.offset;
+ // If this tag isn't useful, tell the stream to stop processing data until the tag ends
+ if (typeof TAGS[ebmlID] === 'undefined') {
+ if (chunk.length > offset + dataLength) {
+ return { offset: offset + dataLength };
+ }
+ return { offset, _skipUntil: this._count + offset + dataLength };
+ }
+
+ const tagHasChildren = TAGS[ebmlID];
+ if (tagHasChildren) {
+ return { offset };
+ }
+
+ if (offset + dataLength > chunk.length) return TOO_SHORT;
+ const data = chunk.slice(offset, offset + dataLength);
+ if (!this._track) {
+ if (ebmlID === 'ae') this._incompleteTrack = {};
+ if (ebmlID === 'd7') this._incompleteTrack.number = data[0];
+ if (ebmlID === '83') this._incompleteTrack.type = data[0];
+ if (this._incompleteTrack.type === 2 && typeof this._incompleteTrack.number !== 'undefined') {
+ this._track = this._incompleteTrack;
+ }
+ }
+ if (ebmlID === '63a2') {
+ this._checkHead(data);
+ this.emit('head', data);
+ } else if (ebmlID === 'a3') {
+ if (!this._track) throw Error('No audio track in this webm!');
+ if ((data[0] & 0xF) === this._track.number) {
+ this.push(data.slice(4));
+ }
+ }
+ return { offset: offset + dataLength };
+ }
+
+ _destroy(err, cb) {
+ this._cleanup();
+ return cb ? cb(err) : undefined;
+ }
+
+ _final(cb) {
+ this._cleanup();
+ cb();
+ }
+
+ /**
+ * Cleans up the demuxer when it is no longer required.
+ * @private
+ */
+ _cleanup() {
+ this._remainder = null;
+ this._incompleteTrack = {};
+ }
+}
+
+/**
+ * A symbol that is returned by some functions that indicates the buffer it has been provided is not large enough
+ * to facilitate a request.
+ * @name WebmBaseDemuxer#TOO_SHORT
+ * @memberof core
+ * @private
+ * @type {Symbol}
+ */
+const TOO_SHORT = WebmBaseDemuxer.TOO_SHORT = Symbol('TOO_SHORT');
+
+/**
+ * A map that takes a value of an EBML ID in hex string form, with the value being a boolean that indicates whether
+ * this tag has children.
+ * @name WebmBaseDemuxer#TAGS
+ * @memberof core
+ * @private
+ * @type {Object}
+ */
+const TAGS = WebmBaseDemuxer.TAGS = { // value is true if the element has children
+ '1a45dfa3': true, // EBML
+ '18538067': true, // Segment
+ '1f43b675': true, // Cluster
+ '1654ae6b': true, // Tracks
+ 'ae': true, // TrackEntry
+ 'd7': false, // TrackNumber
+ '83': false, // TrackType
+ 'a3': false, // SimpleBlock
+ '63a2': false,
+};
+
+module.exports = WebmBaseDemuxer;
+
+function vintLength(buffer, index) {
+ let i = 0;
+ for (; i < 8; i++) if ((1 << (7 - i)) & buffer[index]) break;
+ i++;
+ if (index + i > buffer.length) {
+ return TOO_SHORT;
+ }
+ return i;
+}
+
+function expandVint(buffer, start, end) {
+ const length = vintLength(buffer, start);
+ if (end > buffer.length || length === TOO_SHORT) return TOO_SHORT;
+ let mask = (1 << (8 - length)) - 1;
+ let value = buffer[start] & mask;
+ for (let i = start + 1; i < end; i++) {
+ value = (value << 8) + buffer[i];
+ }
+ return value;
+}
diff --git a/node_modules/prism-media/src/core/index.js b/node_modules/prism-media/src/core/index.js
new file mode 100644
index 0000000..ae9967f
--- /dev/null
+++ b/node_modules/prism-media/src/core/index.js
@@ -0,0 +1,9 @@
+/**
+ * Core features.
+ * **You shouldn't prefix imports from this namespace with `core`.**
+ * @namespace core
+ */
+module.exports = {
+ FFmpeg: require('./FFmpeg'),
+ VolumeTransformer: require('./VolumeTransformer'),
+};
diff --git a/node_modules/prism-media/src/index.js b/node_modules/prism-media/src/index.js
new file mode 100644
index 0000000..ce34849
--- /dev/null
+++ b/node_modules/prism-media/src/index.js
@@ -0,0 +1,5 @@
+module.exports = {
+ opus: require('./opus'),
+ vorbis: require('./vorbis'),
+ ...require('./core'),
+};
diff --git a/node_modules/prism-media/src/opus/OggDemuxer.js b/node_modules/prism-media/src/opus/OggDemuxer.js
new file mode 100644
index 0000000..3ede82a
--- /dev/null
+++ b/node_modules/prism-media/src/opus/OggDemuxer.js
@@ -0,0 +1,143 @@
+const { Transform } = require('stream');
+
+const OGG_PAGE_HEADER_SIZE = 26;
+const STREAM_STRUCTURE_VERSION = 0;
+
+const charCode = x => x.charCodeAt(0);
+const OGGS_HEADER = Buffer.from([...'OggS'].map(charCode));
+const OPUS_HEAD = Buffer.from([...'OpusHead'].map(charCode));
+const OPUS_TAGS = Buffer.from([...'OpusTags'].map(charCode));
+
+/**
+ * Demuxes an Ogg stream (containing Opus audio) to output an Opus stream.
+ * @extends {TransformStream}
+ * @memberof opus
+ */
+class OggDemuxer extends Transform {
+ /**
+ * Creates a new OggOpus demuxer.
+ * @param {Object} [options] options that you would pass to a regular Transform stream.
+ * @memberof opus
+ */
+ constructor(options = {}) {
+ super(Object.assign({ readableObjectMode: true }, options));
+ this._remainder = null;
+ this._head = null;
+ this._bitstream = null;
+ }
+
+ _transform(chunk, encoding, done) {
+ if (this._remainder) {
+ chunk = Buffer.concat([this._remainder, chunk]);
+ this._remainder = null;
+ }
+
+ try {
+ while (chunk) {
+ const result = this._readPage(chunk);
+ if (result) chunk = result;
+ else break;
+ }
+ } catch (error) {
+ done(error);
+ return;
+ }
+ this._remainder = chunk;
+ done();
+ }
+
+ /**
+ * Reads a page from a buffer
+ * @private
+ * @param {Buffer} chunk the chunk containing the page
+ * @returns {boolean|Buffer} if a buffer, it will be a slice of the excess data of the original, otherwise it will be
+ * false and would indicate that there is not enough data to go ahead with reading this page.
+ */
+ _readPage(chunk) {
+ if (chunk.length < OGG_PAGE_HEADER_SIZE) {
+ return false;
+ }
+ if (!chunk.slice(0, 4).equals(OGGS_HEADER)) {
+ throw Error(`capture_pattern is not ${OGGS_HEADER}`);
+ }
+ if (chunk.readUInt8(4) !== STREAM_STRUCTURE_VERSION) {
+ throw Error(`stream_structure_version is not ${STREAM_STRUCTURE_VERSION}`);
+ }
+
+ if (chunk.length < 27) return false;
+ const pageSegments = chunk.readUInt8(26);
+ if (chunk.length < 27 + pageSegments) return false;
+ const table = chunk.slice(27, 27 + pageSegments);
+ const bitstream = chunk.readUInt32BE(14);
+
+ let sizes = [], totalSize = 0;
+
+ for (let i = 0; i < pageSegments;) {
+ let size = 0, x = 255;
+ while (x === 255) {
+ if (i >= table.length) return false;
+ x = table.readUInt8(i);
+ i++;
+ size += x;
+ }
+ sizes.push(size);
+ totalSize += size;
+ }
+
+ if (chunk.length < 27 + pageSegments + totalSize) return false;
+
+ let start = 27 + pageSegments;
+ for (const size of sizes) {
+ const segment = chunk.slice(start, start + size);
+ const header = segment.slice(0, 8);
+ if (this._head) {
+ if (header.equals(OPUS_TAGS)) this.emit('tags', segment);
+ else if (this._bitstream === bitstream) this.push(segment);
+ } else if (header.equals(OPUS_HEAD)) {
+ this.emit('head', segment);
+ this._head = segment;
+ this._bitstream = bitstream;
+ } else {
+ this.emit('unknownSegment', segment);
+ }
+ start += size;
+ }
+ return chunk.slice(start);
+ }
+
+ _destroy(err, cb) {
+ this._cleanup();
+ return cb ? cb(err) : undefined;
+ }
+
+ _final(cb) {
+ this._cleanup();
+ cb();
+ }
+
+ /**
+ * Cleans up the demuxer when it is no longer required.
+ * @private
+ */
+ _cleanup() {
+ this._remainder = null;
+ this._head = null;
+ this._bitstream = null;
+ }
+}
+
+/**
+ * Emitted when the demuxer encounters the opus head.
+ * @event OggDemuxer#head
+ * @memberof opus
+ * @param {Buffer} segment a buffer containing the opus head data.
+ */
+
+/**
+ * Emitted when the demuxer encounters opus tags.
+ * @event OggDemuxer#tags
+ * @memberof opus
+ * @param {Buffer} segment a buffer containing the opus tags.
+ */
+
+module.exports = OggDemuxer;
diff --git a/node_modules/prism-media/src/opus/Opus.js b/node_modules/prism-media/src/opus/Opus.js
new file mode 100644
index 0000000..d8d6c29
--- /dev/null
+++ b/node_modules/prism-media/src/opus/Opus.js
@@ -0,0 +1,212 @@
+// Partly based on https://github.com/Rantanen/node-opus/blob/master/lib/Encoder.js
+
+const { Transform } = require('stream');
+const loader = require('../util/loader');
+
+const CTL = {
+ BITRATE: 4002,
+ FEC: 4012,
+ PLP: 4014,
+};
+
+let Opus = {};
+
+function loadOpus(refresh = false) {
+ if (Opus.Encoder && !refresh) return Opus;
+
+ Opus = loader.require([
+ ['@discordjs/opus', opus => ({ Encoder: opus.OpusEncoder })],
+ ['node-opus', opus => ({ Encoder: opus.OpusEncoder })],
+ ['opusscript', opus => ({ Encoder: opus })],
+ ]);
+ return Opus;
+}
+
+const charCode = x => x.charCodeAt(0);
+const OPUS_HEAD = Buffer.from([...'OpusHead'].map(charCode));
+const OPUS_TAGS = Buffer.from([...'OpusTags'].map(charCode));
+
+// frame size = (channels * rate * frame_duration) / 1000
+
+/**
+ * Takes a stream of Opus data and outputs a stream of PCM data, or the inverse.
+ * **You shouldn't directly instantiate this class, see opus.Encoder and opus.Decoder instead!**
+ * @memberof opus
+ * @extends TransformStream
+ * @protected
+ */
+class OpusStream extends Transform {
+ /**
+ * Creates a new Opus transformer.
+ * @private
+ * @memberof opus
+ * @param {Object} [options] options that you would pass to a regular Transform stream
+ */
+ constructor(options = {}) {
+ if (!loadOpus().Encoder) {
+ throw Error('Could not find an Opus module! Please install @discordjs/opus, node-opus, or opusscript.');
+ }
+ super(Object.assign({ readableObjectMode: true }, options));
+ if (Opus.name === 'opusscript') {
+ options.application = Opus.Encoder.Application[options.application];
+ }
+ this.encoder = new Opus.Encoder(options.rate, options.channels, options.application);
+
+ this._options = options;
+ this._required = this._options.frameSize * this._options.channels * 2;
+ }
+
+ _encode(buffer) {
+ return this.encoder.encode(buffer, this._options.frameSize);
+ }
+
+ _decode(buffer) {
+ return this.encoder.decode(buffer, Opus.name === 'opusscript' ? null : this._options.frameSize);
+ }
+
+ /**
+ * Returns the Opus module being used - `opusscript`, `node-opus`, or `@discordjs/opus`.
+ * @type {string}
+ * @readonly
+ * @example
+ * console.log(`Using Opus module ${prism.opus.Encoder.type}`);
+ */
+ static get type() {
+ return Opus.name;
+ }
+
+ /**
+ * Sets the bitrate of the stream.
+ * @param {number} bitrate the bitrate to use use, e.g. 48000
+ * @public
+ */
+ setBitrate(bitrate) {
+ (this.encoder.applyEncoderCTL || this.encoder.encoderCTL)
+ .apply(this.encoder, [CTL.BITRATE, Math.min(128e3, Math.max(16e3, bitrate))]);
+ }
+
+ /**
+ * Enables or disables forward error correction.
+ * @param {boolean} enabled whether or not to enable FEC.
+ * @public
+ */
+ setFEC(enabled) {
+ (this.encoder.applyEncoderCTL || this.encoder.encoderCTL)
+ .apply(this.encoder, [CTL.FEC, enabled ? 1 : 0]);
+ }
+
+ /**
+ * Sets the expected packet loss over network transmission.
+ * @param {number} [percentage] a percentage (represented between 0 and 1)
+ */
+ setPLP(percentage) {
+ (this.encoder.applyEncoderCTL || this.encoder.encoderCTL)
+ .apply(this.encoder, [CTL.PLP, Math.min(100, Math.max(0, percentage * 100))]);
+ }
+
+ _final(cb) {
+ this._cleanup();
+ cb();
+ }
+
+ _destroy(err, cb) {
+ this._cleanup();
+ return cb ? cb(err) : undefined;
+ }
+
+ /**
+ * Cleans up the Opus stream when it is no longer needed
+ * @private
+ */
+ _cleanup() {
+ if (Opus.name === 'opusscript' && this.encoder) this.encoder.delete();
+ this.encoder = null;
+ }
+}
+
+/**
+ * An Opus encoder stream.
+ *
+ * Outputs opus packets in [object mode.](https://nodejs.org/api/stream.html#stream_object_mode)
+ * @extends opus.OpusStream
+ * @memberof opus
+ * @example
+ * const encoder = new prism.opus.Encoder({ frameSize: 960, channels: 2, rate: 48000 });
+ * pcmAudio.pipe(encoder);
+ * // encoder will now output Opus-encoded audio packets
+ */
+class Encoder extends OpusStream {
+ /**
+ * Creates a new Opus encoder stream.
+ * @memberof opus
+ * @param {Object} options options that you would pass to a regular OpusStream, plus a few more:
+ * @param {number} options.frameSize the frame size in bytes to use (e.g. 960 for stereo audio at 48KHz with a frame
+ * duration of 20ms)
+ * @param {number} options.channels the number of channels to use
+ * @param {number} options.rate the sampling rate in Hz
+ */
+ constructor(options) {
+ super(options);
+ this._buffer = Buffer.alloc(0);
+ }
+
+ _transform(chunk, encoding, done) {
+ this._buffer = Buffer.concat([this._buffer, chunk]);
+ let n = 0;
+ while (this._buffer.length >= this._required * (n + 1)) {
+ const buf = this._encode(this._buffer.slice(n * this._required, (n + 1) * this._required));
+ this.push(buf);
+ n++;
+ }
+ if (n > 0) this._buffer = this._buffer.slice(n * this._required);
+ return done();
+ }
+
+ _destroy(err, cb) {
+ super._destroy(err, cb);
+ this._buffer = null;
+ }
+}
+
+/**
+ * An Opus decoder stream.
+ *
+ * Note that any stream you pipe into this must be in
+ * [object mode](https://nodejs.org/api/stream.html#stream_object_mode) and should output Opus packets.
+ * @extends opus.OpusStream
+ * @memberof opus
+ * @example
+ * const decoder = new prism.opus.Decoder({ frameSize: 960, channels: 2, rate: 48000 });
+ * input.pipe(decoder);
+ * // decoder will now output PCM audio
+ */
+class Decoder extends OpusStream {
+ _transform(chunk, encoding, done) {
+ const signature = chunk.slice(0, 8);
+ if (signature.equals(OPUS_HEAD)) {
+ this.emit('format', {
+ channels: this._options.channels,
+ sampleRate: this._options.rate,
+ bitDepth: 16,
+ float: false,
+ signed: true,
+ version: chunk.readUInt8(8),
+ preSkip: chunk.readUInt16LE(10),
+ gain: chunk.readUInt16LE(16),
+ });
+ return done();
+ }
+ if (signature.equals(OPUS_TAGS)) {
+ this.emit('tags', chunk);
+ return done();
+ }
+ try {
+ this.push(this._decode(chunk));
+ } catch (e) {
+ return done(e);
+ }
+ return done();
+ }
+}
+
+module.exports = { Decoder, Encoder };
diff --git a/node_modules/prism-media/src/opus/WebmDemuxer.js b/node_modules/prism-media/src/opus/WebmDemuxer.js
new file mode 100644
index 0000000..4d78f9c
--- /dev/null
+++ b/node_modules/prism-media/src/opus/WebmDemuxer.js
@@ -0,0 +1,24 @@
+const WebmBaseDemuxer = require('../core/WebmBase');
+
+const OPUS_HEAD = Buffer.from([...'OpusHead'].map(x => x.charCodeAt(0)));
+
+/**
+ * Demuxes a Webm stream (containing Opus audio) to output an Opus stream.
+ * @extends core.WebmBaseDemuxer
+ * @memberof opus
+ * @example
+ * const fs = require('fs');
+ * const file = fs.createReadStream('./audio.webm');
+ * const demuxer = new prism.opus.WebmDemuxer();
+ * const opus = file.pipe(demuxer);
+ * // opus is now a ReadableStream in object mode outputting Opus packets
+ */
+class WebmDemuxer extends WebmBaseDemuxer {
+ _checkHead(data) {
+ if (!data.slice(0, 8).equals(OPUS_HEAD)) {
+ throw Error('Audio codec is not Opus!');
+ }
+ }
+}
+
+module.exports = WebmDemuxer;
diff --git a/node_modules/prism-media/src/opus/index.js b/node_modules/prism-media/src/opus/index.js
new file mode 100644
index 0000000..3532fdc
--- /dev/null
+++ b/node_modules/prism-media/src/opus/index.js
@@ -0,0 +1,10 @@
+/**
+ * Opus features
+ * @namespace opus
+ */
+module.exports = {
+ // Encoder and Decoder
+ ...require('./Opus'),
+ OggDemuxer: require('./OggDemuxer'),
+ WebmDemuxer: require('./WebmDemuxer'),
+};
diff --git a/node_modules/prism-media/src/util/loader.js b/node_modules/prism-media/src/util/loader.js
new file mode 100644
index 0000000..1b1deab
--- /dev/null
+++ b/node_modules/prism-media/src/util/loader.js
@@ -0,0 +1,13 @@
+exports.require = function loader(list) {
+ const errorLog = [];
+ for (const [name, fn] of list) {
+ try {
+ const data = fn(require(name));
+ data.name = name;
+ return data;
+ } catch (e) {
+ errorLog.push(e);
+ }
+ }
+ throw new Error(errorLog.join('\n'));
+};
diff --git a/node_modules/prism-media/src/vorbis/WebmDemuxer.js b/node_modules/prism-media/src/vorbis/WebmDemuxer.js
new file mode 100644
index 0000000..9ef84dc
--- /dev/null
+++ b/node_modules/prism-media/src/vorbis/WebmDemuxer.js
@@ -0,0 +1,22 @@
+const WebmBaseDemuxer = require('../core/WebmBase');
+
+const VORBIS_HEAD = Buffer.from([...'vorbis'].map(x => x.charCodeAt(0)));
+
+/**
+ * Demuxes a Webm stream (containing Vorbis audio) to output a Vorbis stream.
+ * @memberof vorbis
+ * @extends core.WebmBaseDemuxer
+ */
+class WebmDemuxer extends WebmBaseDemuxer {
+ _checkHead(data) {
+ if (data.readUInt8(0) !== 2 || !data.slice(4, 10).equals(VORBIS_HEAD)) {
+ throw Error('Audio codec is not Vorbis!');
+ }
+
+ this.push(data.slice(3, 3 + data.readUInt8(1)));
+ this.push(data.slice(3 + data.readUInt8(1), 3 + data.readUInt8(1) + data.readUInt8(2)));
+ this.push(data.slice(3 + data.readUInt8(1) + data.readUInt8(2)));
+ }
+}
+
+module.exports = WebmDemuxer;
diff --git a/node_modules/prism-media/src/vorbis/index.js b/node_modules/prism-media/src/vorbis/index.js
new file mode 100644
index 0000000..9d06df8
--- /dev/null
+++ b/node_modules/prism-media/src/vorbis/index.js
@@ -0,0 +1,8 @@
+/**
+ * Vorbis features
+ * @namespace vorbis
+ */
+
+module.exports = {
+ WebmDemuxer: require('./WebmDemuxer'),
+};
diff --git a/node_modules/prism-media/typings/index.d.ts b/node_modules/prism-media/typings/index.d.ts
new file mode 100644
index 0000000..cd980d3
--- /dev/null
+++ b/node_modules/prism-media/typings/index.d.ts
@@ -0,0 +1,43 @@
+import { Transform } from 'stream';
+
+import { ChildProcess } from 'child_process';
+import { Duplex } from 'stream';
+
+import { opus } from './opus';
+import { vorbis } from './vorbis';
+
+export interface FFmpegOptions {
+ args?: string[];
+ shell?: boolean;
+}
+
+export interface FFmpegInfo {
+ command: string;
+ info: string;
+ version: string;
+ output: string;
+}
+
+export class FFmpeg extends Duplex {
+ public process: ChildProcess;
+ constructor(options?: FFmpegOptions);
+ static getInfo(force?: boolean): FFmpegInfo;
+}
+
+export interface VolumeOptions {
+ type: 's16le' | 's16be' | 's32le' | 's32be',
+ volume?: number
+}
+
+export class VolumeTransformer extends Transform {
+ public volume: number;
+
+ constructor(options: VolumeOptions);
+ public setVolume(volume: number): void;
+ public setVolumeDecibels(db: number): void;
+ public setVolumeLogarithmic(value: number): void;
+ public readonly volumeDecibels: number;
+ public readonly volumeLogarithmic: number;
+}
+
+export { opus, vorbis };
diff --git a/node_modules/prism-media/typings/opus.d.ts b/node_modules/prism-media/typings/opus.d.ts
new file mode 100644
index 0000000..b37facb
--- /dev/null
+++ b/node_modules/prism-media/typings/opus.d.ts
@@ -0,0 +1,30 @@
+import { Transform } from 'stream';
+
+interface OpusOptions {
+ frameSize: number,
+ channels: number,
+ rate: number
+}
+
+export class OpusStream extends Transform {
+ public encoder: any; // TODO: type opusscript/node-opus
+
+ constructor(options?: OpusOptions);
+ public static readonly type: 'opusscript' | 'node-opus' | '@discordjs/opus';
+ public setBitrate(bitrate: number): void;
+ public setFEC(enabled: boolean): void;
+ public setPLP(percentage: number): void;
+}
+
+export namespace opus {
+ interface OpusOptions {
+ frameSize: number,
+ channels: number,
+ rate: number
+ }
+
+ export class Encoder extends OpusStream {}
+ export class Decoder extends OpusStream {}
+ export class OggDemuxer extends Transform {}
+ export class WebmDemuxer extends Transform {}
+}
\ No newline at end of file
diff --git a/node_modules/prism-media/typings/vorbis.d.ts b/node_modules/prism-media/typings/vorbis.d.ts
new file mode 100644
index 0000000..6c18898
--- /dev/null
+++ b/node_modules/prism-media/typings/vorbis.d.ts
@@ -0,0 +1,5 @@
+import { Transform } from 'stream';
+
+export namespace vorbis {
+ export class WebmDemuxer extends Transform {}
+}
\ No newline at end of file
diff --git a/node_modules/sax/LICENSE b/node_modules/sax/LICENSE
new file mode 100644
index 0000000..ccffa08
--- /dev/null
+++ b/node_modules/sax/LICENSE
@@ -0,0 +1,41 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+====
+
+`String.fromCodePoint` by Mathias Bynens used according to terms of MIT
+License, as follows:
+
+ Copyright Mathias Bynens
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/sax/README.md b/node_modules/sax/README.md
new file mode 100644
index 0000000..afcd3f3
--- /dev/null
+++ b/node_modules/sax/README.md
@@ -0,0 +1,225 @@
+# sax js
+
+A sax-style parser for XML and HTML.
+
+Designed with [node](http://nodejs.org/) in mind, but should work fine in
+the browser or other CommonJS implementations.
+
+## What This Is
+
+* A very simple tool to parse through an XML string.
+* A stepping stone to a streaming HTML parser.
+* A handy way to deal with RSS and other mostly-ok-but-kinda-broken XML
+ docs.
+
+## What This Is (probably) Not
+
+* An HTML Parser - That's a fine goal, but this isn't it. It's just
+ XML.
+* A DOM Builder - You can use it to build an object model out of XML,
+ but it doesn't do that out of the box.
+* XSLT - No DOM = no querying.
+* 100% Compliant with (some other SAX implementation) - Most SAX
+ implementations are in Java and do a lot more than this does.
+* An XML Validator - It does a little validation when in strict mode, but
+ not much.
+* A Schema-Aware XSD Thing - Schemas are an exercise in fetishistic
+ masochism.
+* A DTD-aware Thing - Fetching DTDs is a much bigger job.
+
+## Regarding `Hello, world!').close();
+
+// stream usage
+// takes the same options as the parser
+var saxStream = require("sax").createStream(strict, options)
+saxStream.on("error", function (e) {
+ // unhandled errors will throw, since this is a proper node
+ // event emitter.
+ console.error("error!", e)
+ // clear the error
+ this._parser.error = null
+ this._parser.resume()
+})
+saxStream.on("opentag", function (node) {
+ // same object as above
+})
+// pipe is supported, and it's readable/writable
+// same chunks coming in also go out.
+fs.createReadStream("file.xml")
+ .pipe(saxStream)
+ .pipe(fs.createWriteStream("file-copy.xml"))
+```
+
+
+## Arguments
+
+Pass the following arguments to the parser function. All are optional.
+
+`strict` - Boolean. Whether or not to be a jerk. Default: `false`.
+
+`opt` - Object bag of settings regarding string formatting. All default to `false`.
+
+Settings supported:
+
+* `trim` - Boolean. Whether or not to trim text and comment nodes.
+* `normalize` - Boolean. If true, then turn any whitespace into a single
+ space.
+* `lowercase` - Boolean. If true, then lowercase tag names and attribute names
+ in loose mode, rather than uppercasing them.
+* `xmlns` - Boolean. If true, then namespaces are supported.
+* `position` - Boolean. If false, then don't track line/col/position.
+* `strictEntities` - Boolean. If true, only parse [predefined XML
+ entities](http://www.w3.org/TR/REC-xml/#sec-predefined-ent)
+ (`&`, `'`, `>`, `<`, and `"`)
+
+## Methods
+
+`write` - Write bytes onto the stream. You don't have to do this all at
+once. You can keep writing as much as you want.
+
+`close` - Close the stream. Once closed, no more data may be written until
+it is done processing the buffer, which is signaled by the `end` event.
+
+`resume` - To gracefully handle errors, assign a listener to the `error`
+event. Then, when the error is taken care of, you can call `resume` to
+continue parsing. Otherwise, the parser will not continue while in an error
+state.
+
+## Members
+
+At all times, the parser object will have the following members:
+
+`line`, `column`, `position` - Indications of the position in the XML
+document where the parser currently is looking.
+
+`startTagPosition` - Indicates the position where the current tag starts.
+
+`closed` - Boolean indicating whether or not the parser can be written to.
+If it's `true`, then wait for the `ready` event to write again.
+
+`strict` - Boolean indicating whether or not the parser is a jerk.
+
+`opt` - Any options passed into the constructor.
+
+`tag` - The current tag being dealt with.
+
+And a bunch of other stuff that you probably shouldn't touch.
+
+## Events
+
+All events emit with a single argument. To listen to an event, assign a
+function to `on`. Functions get executed in the this-context of
+the parser object. The list of supported events are also in the exported
+`EVENTS` array.
+
+When using the stream interface, assign handlers using the EventEmitter
+`on` function in the normal fashion.
+
+`error` - Indication that something bad happened. The error will be hanging
+out on `parser.error`, and must be deleted before parsing can continue. By
+listening to this event, you can keep an eye on that kind of stuff. Note:
+this happens *much* more in strict mode. Argument: instance of `Error`.
+
+`text` - Text node. Argument: string of text.
+
+`doctype` - The ``. Argument:
+object with `name` and `body` members. Attributes are not parsed, as
+processing instructions have implementation dependent semantics.
+
+`sgmldeclaration` - Random SGML declarations. Stuff like ``
+would trigger this kind of event. This is a weird thing to support, so it
+might go away at some point. SAX isn't intended to be used to parse SGML,
+after all.
+
+`opentagstart` - Emitted immediately when the tag name is available,
+but before any attributes are encountered. Argument: object with a
+`name` field and an empty `attributes` set. Note that this is the
+same object that will later be emitted in the `opentag` event.
+
+`opentag` - An opening tag. Argument: object with `name` and `attributes`.
+In non-strict mode, tag names are uppercased, unless the `lowercase`
+option is set. If the `xmlns` option is set, then it will contain
+namespace binding information on the `ns` member, and will have a
+`local`, `prefix`, and `uri` member.
+
+`closetag` - A closing tag. In loose mode, tags are auto-closed if their
+parent closes. In strict mode, well-formedness is enforced. Note that
+self-closing tags will have `closeTag` emitted immediately after `openTag`.
+Argument: tag name.
+
+`attribute` - An attribute node. Argument: object with `name` and `value`.
+In non-strict mode, attribute names are uppercased, unless the `lowercase`
+option is set. If the `xmlns` option is set, it will also contains namespace
+information.
+
+`comment` - A comment node. Argument: the string of the comment.
+
+`opencdata` - The opening tag of a ``) of a `` tags trigger a `"script"`
+event, and their contents are not checked for special xml characters.
+If you pass `noscript: true`, then this behavior is suppressed.
+
+## Reporting Problems
+
+It's best to write a failing test if you find an issue. I will always
+accept pull requests with failing tests if they demonstrate intended
+behavior, but it is very hard to figure out what issue you're describing
+without a test. Writing a test is also the best way for you yourself
+to figure out if you really understand the issue you think you have with
+sax-js.
diff --git a/node_modules/sax/lib/sax.js b/node_modules/sax/lib/sax.js
new file mode 100644
index 0000000..795d607
--- /dev/null
+++ b/node_modules/sax/lib/sax.js
@@ -0,0 +1,1565 @@
+;(function (sax) { // wrapper for non-node envs
+ sax.parser = function (strict, opt) { return new SAXParser(strict, opt) }
+ sax.SAXParser = SAXParser
+ sax.SAXStream = SAXStream
+ sax.createStream = createStream
+
+ // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns.
+ // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)),
+ // since that's the earliest that a buffer overrun could occur. This way, checks are
+ // as rare as required, but as often as necessary to ensure never crossing this bound.
+ // Furthermore, buffers are only tested at most once per write(), so passing a very
+ // large string into write() might have undesirable effects, but this is manageable by
+ // the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme
+ // edge case, result in creating at most one complete copy of the string passed in.
+ // Set to Infinity to have unlimited buffers.
+ sax.MAX_BUFFER_LENGTH = 64 * 1024
+
+ var buffers = [
+ 'comment', 'sgmlDecl', 'textNode', 'tagName', 'doctype',
+ 'procInstName', 'procInstBody', 'entity', 'attribName',
+ 'attribValue', 'cdata', 'script'
+ ]
+
+ sax.EVENTS = [
+ 'text',
+ 'processinginstruction',
+ 'sgmldeclaration',
+ 'doctype',
+ 'comment',
+ 'opentagstart',
+ 'attribute',
+ 'opentag',
+ 'closetag',
+ 'opencdata',
+ 'cdata',
+ 'closecdata',
+ 'error',
+ 'end',
+ 'ready',
+ 'script',
+ 'opennamespace',
+ 'closenamespace'
+ ]
+
+ function SAXParser (strict, opt) {
+ if (!(this instanceof SAXParser)) {
+ return new SAXParser(strict, opt)
+ }
+
+ var parser = this
+ clearBuffers(parser)
+ parser.q = parser.c = ''
+ parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH
+ parser.opt = opt || {}
+ parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags
+ parser.looseCase = parser.opt.lowercase ? 'toLowerCase' : 'toUpperCase'
+ parser.tags = []
+ parser.closed = parser.closedRoot = parser.sawRoot = false
+ parser.tag = parser.error = null
+ parser.strict = !!strict
+ parser.noscript = !!(strict || parser.opt.noscript)
+ parser.state = S.BEGIN
+ parser.strictEntities = parser.opt.strictEntities
+ parser.ENTITIES = parser.strictEntities ? Object.create(sax.XML_ENTITIES) : Object.create(sax.ENTITIES)
+ parser.attribList = []
+
+ // namespaces form a prototype chain.
+ // it always points at the current tag,
+ // which protos to its parent tag.
+ if (parser.opt.xmlns) {
+ parser.ns = Object.create(rootNS)
+ }
+
+ // mostly just for error reporting
+ parser.trackPosition = parser.opt.position !== false
+ if (parser.trackPosition) {
+ parser.position = parser.line = parser.column = 0
+ }
+ emit(parser, 'onready')
+ }
+
+ if (!Object.create) {
+ Object.create = function (o) {
+ function F () {}
+ F.prototype = o
+ var newf = new F()
+ return newf
+ }
+ }
+
+ if (!Object.keys) {
+ Object.keys = function (o) {
+ var a = []
+ for (var i in o) if (o.hasOwnProperty(i)) a.push(i)
+ return a
+ }
+ }
+
+ function checkBufferLength (parser) {
+ var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10)
+ var maxActual = 0
+ for (var i = 0, l = buffers.length; i < l; i++) {
+ var len = parser[buffers[i]].length
+ if (len > maxAllowed) {
+ // Text/cdata nodes can get big, and since they're buffered,
+ // we can get here under normal conditions.
+ // Avoid issues by emitting the text node now,
+ // so at least it won't get any bigger.
+ switch (buffers[i]) {
+ case 'textNode':
+ closeText(parser)
+ break
+
+ case 'cdata':
+ emitNode(parser, 'oncdata', parser.cdata)
+ parser.cdata = ''
+ break
+
+ case 'script':
+ emitNode(parser, 'onscript', parser.script)
+ parser.script = ''
+ break
+
+ default:
+ error(parser, 'Max buffer length exceeded: ' + buffers[i])
+ }
+ }
+ maxActual = Math.max(maxActual, len)
+ }
+ // schedule the next check for the earliest possible buffer overrun.
+ var m = sax.MAX_BUFFER_LENGTH - maxActual
+ parser.bufferCheckPosition = m + parser.position
+ }
+
+ function clearBuffers (parser) {
+ for (var i = 0, l = buffers.length; i < l; i++) {
+ parser[buffers[i]] = ''
+ }
+ }
+
+ function flushBuffers (parser) {
+ closeText(parser)
+ if (parser.cdata !== '') {
+ emitNode(parser, 'oncdata', parser.cdata)
+ parser.cdata = ''
+ }
+ if (parser.script !== '') {
+ emitNode(parser, 'onscript', parser.script)
+ parser.script = ''
+ }
+ }
+
+ SAXParser.prototype = {
+ end: function () { end(this) },
+ write: write,
+ resume: function () { this.error = null; return this },
+ close: function () { return this.write(null) },
+ flush: function () { flushBuffers(this) }
+ }
+
+ var Stream
+ try {
+ Stream = require('stream').Stream
+ } catch (ex) {
+ Stream = function () {}
+ }
+
+ var streamWraps = sax.EVENTS.filter(function (ev) {
+ return ev !== 'error' && ev !== 'end'
+ })
+
+ function createStream (strict, opt) {
+ return new SAXStream(strict, opt)
+ }
+
+ function SAXStream (strict, opt) {
+ if (!(this instanceof SAXStream)) {
+ return new SAXStream(strict, opt)
+ }
+
+ Stream.apply(this)
+
+ this._parser = new SAXParser(strict, opt)
+ this.writable = true
+ this.readable = true
+
+ var me = this
+
+ this._parser.onend = function () {
+ me.emit('end')
+ }
+
+ this._parser.onerror = function (er) {
+ me.emit('error', er)
+
+ // if didn't throw, then means error was handled.
+ // go ahead and clear error, so we can write again.
+ me._parser.error = null
+ }
+
+ this._decoder = null
+
+ streamWraps.forEach(function (ev) {
+ Object.defineProperty(me, 'on' + ev, {
+ get: function () {
+ return me._parser['on' + ev]
+ },
+ set: function (h) {
+ if (!h) {
+ me.removeAllListeners(ev)
+ me._parser['on' + ev] = h
+ return h
+ }
+ me.on(ev, h)
+ },
+ enumerable: true,
+ configurable: false
+ })
+ })
+ }
+
+ SAXStream.prototype = Object.create(Stream.prototype, {
+ constructor: {
+ value: SAXStream
+ }
+ })
+
+ SAXStream.prototype.write = function (data) {
+ if (typeof Buffer === 'function' &&
+ typeof Buffer.isBuffer === 'function' &&
+ Buffer.isBuffer(data)) {
+ if (!this._decoder) {
+ var SD = require('string_decoder').StringDecoder
+ this._decoder = new SD('utf8')
+ }
+ data = this._decoder.write(data)
+ }
+
+ this._parser.write(data.toString())
+ this.emit('data', data)
+ return true
+ }
+
+ SAXStream.prototype.end = function (chunk) {
+ if (chunk && chunk.length) {
+ this.write(chunk)
+ }
+ this._parser.end()
+ return true
+ }
+
+ SAXStream.prototype.on = function (ev, handler) {
+ var me = this
+ if (!me._parser['on' + ev] && streamWraps.indexOf(ev) !== -1) {
+ me._parser['on' + ev] = function () {
+ var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments)
+ args.splice(0, 0, ev)
+ me.emit.apply(me, args)
+ }
+ }
+
+ return Stream.prototype.on.call(me, ev, handler)
+ }
+
+ // this really needs to be replaced with character classes.
+ // XML allows all manner of ridiculous numbers and digits.
+ var CDATA = '[CDATA['
+ var DOCTYPE = 'DOCTYPE'
+ var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'
+ var XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/'
+ var rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE }
+
+ // http://www.w3.org/TR/REC-xml/#NT-NameStartChar
+ // This implementation works on strings, a single character at a time
+ // as such, it cannot ever support astral-plane characters (10000-EFFFF)
+ // without a significant breaking change to either this parser, or the
+ // JavaScript language. Implementation of an emoji-capable xml parser
+ // is left as an exercise for the reader.
+ var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
+
+ var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/
+
+ var entityStart = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
+ var entityBody = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/
+
+ function isWhitespace (c) {
+ return c === ' ' || c === '\n' || c === '\r' || c === '\t'
+ }
+
+ function isQuote (c) {
+ return c === '"' || c === '\''
+ }
+
+ function isAttribEnd (c) {
+ return c === '>' || isWhitespace(c)
+ }
+
+ function isMatch (regex, c) {
+ return regex.test(c)
+ }
+
+ function notMatch (regex, c) {
+ return !isMatch(regex, c)
+ }
+
+ var S = 0
+ sax.STATE = {
+ BEGIN: S++, // leading byte order mark or whitespace
+ BEGIN_WHITESPACE: S++, // leading whitespace
+ TEXT: S++, // general stuff
+ TEXT_ENTITY: S++, // & and such.
+ OPEN_WAKA: S++, // <
+ SGML_DECL: S++, //
+ SCRIPT: S++, // ', '{');
+ } catch (err) {
+ let args = findJSON('watch.html', 'player_response', body, /\bytplayer\.config\s*=\s*{/, '', '{');
+ info.player_response = findPlayerResponse('watch.html', args);
+ }
+ info.response = findJSON('watch.html', 'response', body, /\bytInitialData("\])?\s*=\s*\{/i, '', '{');
+ info.html5player = getHTML5player(body);
+ return info;
+};
+
+
+const INFO_HOST = 'www.youtube.com';
+const INFO_PATH = '/get_video_info';
+const VIDEO_EURL = 'https://youtube.googleapis.com/v/';
+const getVideoInfoPage = async(id, options) => {
+ const url = new URL(`https://${INFO_HOST}${INFO_PATH}`);
+ url.searchParams.set('video_id', id);
+ url.searchParams.set('c', 'TVHTML5');
+ url.searchParams.set('cver', `7${cver.substr(1)}`);
+ url.searchParams.set('eurl', VIDEO_EURL + id);
+ url.searchParams.set('ps', 'default');
+ url.searchParams.set('gl', 'US');
+ url.searchParams.set('hl', options.lang || 'en');
+ url.searchParams.set('html5', '1');
+ const body = await utils.exposedMiniget(url.toString(), options).text();
+ let info = querystring.parse(body);
+ info.player_response = findPlayerResponse('get_video_info', info);
+ return info;
+};
+
+
+/**
+ * @param {Object} player_response
+ * @returns {Array.