chaosdc/node_modules/@discord-player/ffmpeg/dist/index.js

292 lines
26 KiB
JavaScript

"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
// src/index.ts
var src_exports = {};
__export(src_exports, {
FFmpeg: () => FFmpeg,
changeFFmpegFlags: () => changeFFmpegFlags,
createFFmpegArgs: () => createFFmpegArgs,
version: () => version
});
module.exports = __toCommonJS(src_exports);
// src/FFmpeg.ts
var import_node_child_process = require("child_process");
var import_node_stream = require("stream");
var VERSION_REGEX = /version (.+) Copyright/im;
var validatePathParam = /* @__PURE__ */ __name((path, displayName) => {
if (!path) throw new Error(`Failed to resolve ${displayName}`);
return path;
}, "validatePathParam");
var _FFmpeg = class _FFmpeg extends import_node_stream.Duplex {
/**
* Create FFmpeg duplex stream
* @param options Options to initialize ffmpeg
* @example ```typescript
* const ffmpeg = new FFmpeg({
* args: [
* '-analyzeduration', '0',
* '-loglevel', '0',
* '-f', 's16le',
* '-ar', '48000',
* '-ac', '2',
* '-af', 'bass=g=10,acompressor'
* ]
* });
*
* const pcm = input.pipe(ffmpeg);
*
* pcm.pipe(fs.createWriteStream('./audio.pcm'));
* ```
*/
constructor(options = {}) {
super(options);
/**
* Current FFmpeg process
*/
__publicField(this, "process");
this.process = _FFmpeg.spawn(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",
"removeAllListeners",
"listeners"
]) {
this[method] = (ev, fn) => (
// @ts-expect-error
EVENTS[ev] ? (
// @ts-expect-error
EVENTS[ev][method](ev, fn)
) : (
// @ts-expect-error
import_node_stream.Duplex.prototype[method].call(this, ev, fn)
)
);
}
const processError = /* @__PURE__ */ __name((error) => this.emit("error", error), "processError");
this._reader.on("error", processError);
this._writer.on("error", processError);
}
/**
* Checks if FFmpeg is loaded.
*/
static isLoaded() {
return _FFmpeg.cached != null;
}
/**
* Adds a new FFmpeg source.
* @param source FFmpeg source
*/
static addSource(source) {
if (_FFmpeg.sources.some((s) => s.name === source.name)) return false;
_FFmpeg.sources.push(source);
return true;
}
/**
* Removes a FFmpeg source.
* @param source FFmpeg source
*/
static removeSource(source) {
const index = _FFmpeg.sources.findIndex((s) => s.name === source.name);
if (index === -1) return false;
_FFmpeg.sources.splice(index, 1);
return true;
}
/**
* Resolves FFmpeg path. Throws an error if it fails to resolve.
* @param force if it should relocate the command
*/
static resolve(force = false) {
if (!force && _FFmpeg.cached) return _FFmpeg.cached;
const errors = [];
for (const source of _FFmpeg.sources) {
try {
let path;
if (source.module) {
const mod = require(source.name);
path = validatePathParam(
mod.default?.path || mod.path || mod,
source.name
);
} else {
path = source.name;
}
const result = (0, import_node_child_process.spawnSync)(path, ["-v"], { windowsHide: true });
const resolved = {
result: result.stdout.toString(),
command: path,
module: source.module,
name: source.name,
path,
version: VERSION_REGEX.exec(result.stderr.toString())?.[1] ?? "unknown"
};
_FFmpeg.cached = resolved;
errors.length = 0;
return resolved;
} catch (e) {
const err = e && e instanceof Error ? e.message : `${e}`;
const msg = `Failed to load ffmpeg using ${source.module ? `require('${source.name}')` : `spawn('${source.name}')`}. Error: ${err}`;
errors.push(msg);
}
}
throw new Error(`Could not load ffmpeg. Errors:
${errors.join("\n")}`);
}
/**
* Resolves FFmpeg path safely. Returns null if it fails to resolve.
* @param force if it should relocate the command
*/
static resolveSafe(force = false) {
try {
return _FFmpeg.resolve(force);
} catch {
return null;
}
}
/**
* Spawns ffmpeg process
* @param options Spawn options
*/
static spawn({ args = [], shell = false } = {}) {
if (!args.includes("-i")) args.unshift("-i", "-");
return (0, import_node_child_process.spawn)(_FFmpeg.resolve().command, args.concat(["pipe:1"]), {
windowsHide: true,
shell
});
}
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();
if (cb) return cb(err);
}
_final(cb) {
this._cleanup();
cb();
}
_cleanup() {
if (this.process) {
this.once("error", () => {
});
this.process.kill("SIGKILL");
this.process = null;
}
}
};
__name(_FFmpeg, "FFmpeg");
/**
* Cached FFmpeg source.
*/
__publicField(_FFmpeg, "cached", null);
/**
* Supported FFmpeg sources.
*/
__publicField(_FFmpeg, "sources", [
// paths
{ name: "ffmpeg", module: false },
{ name: "./ffmpeg", module: false },
{ name: "avconv", module: false },
{ name: "./avconv", module: false },
// modules
{ name: "ffmpeg-static", module: true },
{ name: "@ffmpeg-installer/ffmpeg", module: true },
{ name: "@node-ffmpeg/node-ffmpeg-installer", module: true },
{ name: "ffmpeg-binaries", module: true }
]);
var FFmpeg = _FFmpeg;
// src/common.ts
function changeFFmpegFlags(oldFlags, newFlags) {
const updatedFlags = [...oldFlags];
for (let i = 0; i < newFlags.length; i++) {
const key = newFlags[i];
const value = newFlags[i + 1];
const oldIndex = updatedFlags.indexOf(key);
if (oldIndex !== -1) {
if (value && !value.startsWith("-")) {
updatedFlags[oldIndex + 1] = value;
i++;
} else {
updatedFlags.splice(oldIndex, 1);
}
} else {
if (value && !value.startsWith("-")) {
updatedFlags.push(key, value);
i++;
} else {
updatedFlags.push(key);
}
}
}
return updatedFlags;
}
__name(changeFFmpegFlags, "changeFFmpegFlags");
// src/version.ts
var version = (
/* @__MACRO__ getVersion */
"7.2.0"
);
// src/index.ts
var createFFmpegArgs = /* @__PURE__ */ __name((input, post) => {
const args = [];
for (const [key, value] of Object.entries(input)) {
if (value == null) continue;
args.push(`-${key}`, String(value));
}
if (post) {
Array.isArray(post) ? args.push(...post) : args.push(post);
}
return args;
}, "createFFmpegArgs");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
FFmpeg,
changeFFmpegFlags,
createFFmpegArgs,
version
});
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIiwgIi4uL3NyYy9GRm1wZWcudHMiLCAiLi4vc3JjL2NvbW1vbi50cyIsICIuLi9zcmMvdmVyc2lvbi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiZXhwb3J0ICogZnJvbSAnLi9GRm1wZWcnO1xuXG5leHBvcnQgdHlwZSBBcmdQcmltaXRpdmUgPSBzdHJpbmcgfCBudW1iZXIgfCBudWxsO1xuXG4vKipcbiAqIENyZWF0ZSBGRm1wZWcgYXJndW1lbnRzIGZyb20gYW4gb2JqZWN0LlxuICogQHBhcmFtIGlucHV0IFRoZSBpbnB1dCBvYmplY3QuXG4gKiBAcGFyYW0gcG9zdCBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBhcHBlbmQuXG4gKiBAcmV0dXJucyBUaGUgRkZtcGVnIGFyZ3VtZW50cy5cbiAqIEBleGFtcGxlIGNyZWF0ZUZGbXBlZ0FyZ3MoeyBpOiAnaW5wdXQubXAzJywgYWY6IFsnYmFzcz1nPTEwJywnYWNvbXByZXNzb3InXSB9LCAnLi9vdXQubXAzJyk7XG4gKiAvLyA9PiBbJy1pJywgJ2lucHV0Lm1wMycsICctYWYnLCAnYmFzcz1nPTEwLGFjb21wcmVzc29yJywgJy4vb3V0Lm1wMyddXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVGRm1wZWdBcmdzID0gKFxuaW5wdXQ6IFJlY29yZDxzdHJpbmcsIEFyZ1ByaW1pdGl2ZSB8IEFyZ1ByaW1pdGl2ZVtdPixcbnBvc3Q/OiBzdHJpbmcgfCBzdHJpbmdbXSlcbjogc3RyaW5nW10gPT4ge1xuICBjb25zdCBhcmdzID0gW107XG5cbiAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoaW5wdXQpKSB7XG4gICAgaWYgKHZhbHVlID09IG51bGwpIGNvbnRpbnVlO1xuICAgIGFyZ3MucHVzaChgLSR7a2V5fWAsIFN0cmluZyh2YWx1ZSkpO1xuICB9XG5cbiAgaWYgKHBvc3QpIHtcbiAgICBBcnJheS5pc0FycmF5KHBvc3QpID8gYXJncy5wdXNoKC4uLnBvc3QpIDogYXJncy5wdXNoKHBvc3QpO1xuICB9XG5cbiAgcmV0dXJuIGFyZ3M7XG59O1xuXG5leHBvcnQgKiBmcm9tICcuL2NvbW1vbic7XG5leHBvcnQgeyB2ZXJzaW9uIH0gZnJvbSAnLi92ZXJzaW9uJzsiLCAiaW1wb3J0IHtcbiAgQ2hpbGRQcm9jZXNzV2l0aG91dE51bGxTdHJlYW1zLFxuICBzcGF3bixcbiAgc3Bhd25TeW5jIH0gZnJvbVxuJ25vZGU6Y2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgeyBEdXBsZXgsIER1cGxleE9wdGlvbnMgfSBmcm9tICdub2RlOnN0cmVhbSc7XG5pbXBvcnQgeyBGRm1wZWdDYWxsYmFjaywgRkZtcGVnU291cmNlLCBSZXNvbHZlZEZGbXBlZ1NvdXJjZSB9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBGRm1wZWdPcHRpb25zIGV4dGVuZHMgRHVwbGV4T3B0aW9ucyB7XG4gIGFyZ3M/OiBzdHJpbmdbXTtcbiAgc2hlbGw/OiBib29sZWFuO1xufVxuXG5jb25zdCBWRVJTSU9OX1JFR0VYID0gL3ZlcnNpb24gKC4rKSBDb3B5cmlnaHQvaW07XG5cbmNvbnN0IHZhbGlkYXRlUGF0aFBhcmFtID0gKHBhdGg6IHN0cmluZywgZGlzcGxheU5hbWU6IHN0cmluZykgPT4ge1xuICBpZiAoIXBhdGgpIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHJlc29sdmUgJHtkaXNwbGF5TmFtZX1gKTtcbiAgcmV0dXJuIHBhdGg7XG59O1xuXG5leHBvcnQgY2xhc3MgRkZtcGVnIGV4dGVuZHMgRHVwbGV4IHtcbiAgLyoqXG4gICAqIENhY2hlZCBGRm1wZWcgc291cmNlLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgY2FjaGVkOiBSZXNvbHZlZEZGbXBlZ1NvdXJjZSB8IG51bGwgPSBudWxsO1xuICAvKipcbiAgICogU3VwcG9ydGVkIEZGbXBlZyBzb3VyY2VzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBzb3VyY2VzOiBGRm1wZWdTb3VyY2VbXSA9IFtcbiAgLy8gcGF0aHNcbiAgeyBuYW1lOiAnZmZtcGVnJywgbW9kdWxlOiBmYWxzZSB9LFxuICB7IG5hbWU6ICcuL2ZmbXBlZycsIG1vZHVsZTogZmFsc2UgfSxcbiAgeyBuYW1lOiAnYXZjb252JywgbW9kdWxlOiBmYWxzZSB9LFxuICB7IG5hbWU6ICcuL2F2Y29udicsIG1vZHVsZTogZmFsc2UgfSxcbiAgLy8gbW9kdWxlc1xuICB7IG5hbWU6ICdmZm1wZWctc3RhdGljJywgbW9kdWxlOiB0cnVlIH0sXG4gIHsgbmFtZTogJ0BmZm1wZWctaW5zdGFsbGVyL2ZmbXBlZycsIG1vZHVsZTogdHJ1ZSB9LFxuICB7IG5hbWU6ICdAbm9kZS1mZm1wZWcvbm9kZS1mZm1wZWctaW5zdGFsbGVyJywgbW9kdWxlOiB0cnVlIH0sXG4gIHsgbmFtZTogJ2ZmbXBlZy1iaW5hcmllcycsIG1vZHVsZTogdHJ1ZSB9XTtcblxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgRkZtcGVnIGlzIGxvYWRlZC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaXNMb2FkZWQoKSB7XG4gICAgcmV0dXJuIEZGbXBlZy5jYWNoZWQgIT0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgbmV3IEZGbXBlZyBzb3VyY2UuXG4gICAqIEBwYXJhbSBzb3VyY2UgRkZtcGVnIHNvdXJjZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhZGRTb3VyY2Uoc291cmNlOiBGRm1wZWdTb3VyY2UpIHtcbiAgICBpZiAoRkZtcGVnLnNvdXJjZXMuc29tZSgocykgPT4gcy5uYW1lID09PSBzb3VyY2UubmFtZSkpIHJldHVybiBmYWxzZTtcbiAgICBGRm1wZWcuc291cmNlcy5wdXNoKHNvdXJjZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBhIEZGbXBlZyBzb3VyY2UuXG4gICAqIEBwYXJhbSBzb3VyY2UgRkZtcGVnIHNvdXJjZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZW1vdmVTb3VyY2Uoc291cmNlOiBGRm1wZWdTb3VyY2UpIHtcbiAgICBjb25zdCBpbmRleCA9IEZGbXBlZy5zb3VyY2VzLmZpbmRJbmRleCgocykgPT4gcy5uYW1lID09PSBzb3VyY2UubmFtZSk7XG4gICAgaWYgKGluZGV4ID09PSAtMSkgcmV0dXJuIGZhbHNlO1xuICAgIEZGbXBlZy5zb3VyY2VzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgRkZtcGVnIHBhdGguIFRocm93cyBhbiBlcnJvciBpZiBpdCBmYWlscyB0byByZXNvbHZlLlxuICAgKiBAcGFyYW0gZm9yY2UgaWYgaXQgc2hvdWxkIHJlbG9jYXRlIHRoZSBjb21tYW5kXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlc29sdmUoZm9yY2UgPSBmYWxzZSkge1xuICAgIGlmICghZm9yY2UgJiYgRkZtcGVnLmNhY2hlZCkgcmV0dXJuIEZGbXBlZy5jYWNoZWQ7XG5cbiAgICBjb25zdCBlcnJvcnM6IHN0cmluZ1tdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IHNvdXJjZSBvZiBGRm1wZWcuc291cmNlcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgbGV0IHBhdGg6IHN0cmluZztcblxuICAgICAgICBpZiAoc291cmNlLm1vZHVsZSkge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG4gICAgICAgICAgY29uc3QgbW9kID0gcmVxdWlyZShzb3VyY2UubmFtZSk7XG4gICAgICAgICAgcGF0aCA9IHZhbGlkYXRlUGF0aFBhcmFtKFxuICAgICAgICAgICAgbW9kLmRlZmF1bHQ/LnBhdGggfHwgbW9kLnBhdGggfHwgbW9kLFxuICAgICAgICAgICAgc291cmNlLm5hbWVcbiAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBhdGggPSBzb3VyY2UubmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHNwYXduU3luYyhwYXRoLCBbJy12J10sIHsgd2luZG93c0hpZGU6IHRydWUgfSk7XG5cbiAgICAgICAgY29uc3QgcmVzb2x2ZWQ6IFJlc29sdmVkRkZtcGVnU291cmNlID0ge1xuICAgICAgICAgIHJlc3VsdDogcmVzdWx0LnN0ZG91dC50b1N0cmluZygpLFxuICAgICAgICAgIGNvbW1hbmQ6IHBhdGgsXG4gICAgICAgICAgbW9kdWxlOiBzb3VyY2UubW9kdWxlLFxuICAgICAgICAgIG5hbWU6IHNvdXJjZS5uYW1lLFxuICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgdmVyc2lvbjpcbiAgICAgICAgICBWRVJTSU9OX1JFR0VYLmV4ZWMocmVzdWx0LnN0ZGVyci50b1N0cmluZygpKT8uWzFdID8/ICd1bmtub3duJ1xuICAgICAgICB9O1xuXG4gICAgICAgIEZGbXBlZy5jYWNoZWQgPSByZXNvbHZlZDtcblxuICAgICAgICBlcnJvcnMubGVuZ3RoID0gMDtcblxuICAgICAgICByZXR1cm4gcmVzb2x2ZWQ7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnN0IGVyciA9IGUgJiYgZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogYCR7ZX1gO1xuICAgICAgICBjb25zdCBtc2cgPSBgRmFpbGVkIHRvIGxvYWQgZmZtcGVnIHVzaW5nICR7XG4gICAgICAgIHNvdXJjZS5tb2R1bGUgP1xuICAgICAgICBgcmVxdWlyZSgnJHtzb3VyY2UubmFtZX0nKWAgOlxuICAgICAgICBgc3Bhd24oJyR7c291cmNlLm5hbWV9JylgfS4gRXJyb3I6ICR7XG4gICAgICAgIGVycn1gO1xuXG4gICAgICAgIGVycm9ycy5wdXNoKG1zZyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgbG9hZCBmZm1wZWcuIEVycm9yczpcXG4ke2Vycm9ycy5qb2luKCdcXG4nKX1gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyBGRm1wZWcgcGF0aCBzYWZlbHkuIFJldHVybnMgbnVsbCBpZiBpdCBmYWlscyB0byByZXNvbHZlLlxuICAgKiBAcGFyYW0gZm9yY2UgaWYgaXQgc2hvdWxkIHJlbG9jYXRlIHRoZSBjb21tYW5kXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlc29sdmVTYWZlKGZvcmNlID0gZmFsc2UpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEZGbXBlZy5yZXNvbHZlKGZvcmNlKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTcGF3bnMgZmZtcGVnIHByb2Nlc3NcbiAgICogQHBhcmFtIG9wdGlvbnMgU3Bhd24gb3B0aW9uc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBzcGF3bih7IGFyZ3MgPSBbXSBhcyBzdHJpbmdbXSwgc2hlbGwgPSBmYWxzZSB9ID0ge30pIHtcbiAgICBpZiAoIWFyZ3MuaW5jbHVkZXMoJy1pJykpIGFyZ3MudW5zaGlmdCgnLWknLCAnLScpO1xuICAgIHJldHVybiBzcGF3bihGRm1wZWcucmVzb2x2ZSgpLmNvbW1hbmQsIGFyZ3MuY29uY2F0KFsncGlwZToxJ10pLCB7XG4gICAgICB3aW5kb3dzSGlkZTogdHJ1ZSxcbiAgICAgIHNoZWxsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3VycmVudCBGRm1wZWcgcHJvY2Vzc1xuICAgKi9cbiAgcHVibGljIHByb2Nlc3M6IENoaWxkUHJvY2Vzc1dpdGhvdXROdWxsU3RyZWFtcztcblxuICAvKipcbiAgICogQ3JlYXRlIEZGbXBlZyBkdXBsZXggc3RyZWFtXG4gICAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnMgdG8gaW5pdGlhbGl6ZSBmZm1wZWdcbiAgICogQGV4YW1wbGUgYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBmZm1wZWcgPSBuZXcgRkZtcGVnKHtcbiAgICogICBhcmdzOiBbXG4gICAqICAgICAnLWFuYWx5emVkdXJhdGlvbicsICcwJyxcbiAgICogICAgICctbG9nbGV2ZWwnLCAnMCcsXG4gICAqICAgICAnLWYnLCAnczE2bGUnLFxuICAgKiAgICAgJy1hcicsICc0ODAwMCcsXG4gICAqICAgICAnLWFjJywgJzInLFxuICAgKiAgICAgJy1hZicsICdiYXNzPWc9MTAsYWNvbXByZXNzb3InXG4gICAqICAgXVxuICAgKiB9KTtcbiAgICpcbiAgICogY29uc3QgcGNtID0gaW5wdXQucGlwZShmZm1wZWcpO1xuICAgKlxuICAgKiBwY20ucGlwZShmcy5jcmVhdGVXcml0ZVN0cmVhbSgnLi9hdWRpby5wY20nKSk7XG4gICAqIGBgYFxuICAgKi9cbiAgcHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM6IEZGbXBlZ09wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuXG4gICAgdGhpcy5wcm9jZXNzID0gRkZtcGVnLnNwYXduKG9wdGlvbnMpO1xuXG4gICAgY29uc3QgRVZFTlRTID0ge1xuICAgICAgcmVhZGFibGU6IHRoaXMuX3JlYWRlcixcbiAgICAgIGRhdGE6IHRoaXMuX3JlYWRlcixcbiAgICAgIGVuZDogdGhpcy5fcmVhZGVyLFxuICAgICAgdW5waXBlOiB0aGlzLl9yZWFkZXIsXG4gICAgICBmaW5pc2g6IHRoaXMuX3dyaXRlcixcbiAgICAgIGRyYWluOiB0aGlzLl93cml0ZXJcbiAgICB9IGFzIGNvbnN0O1xuXG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgIHRoaXMuX3JlYWRhYmxlU3RhdGUgPSB0aGlzLl9yZWFkZXIuX3JlYWRhYmxlU3RhdGU7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgIHRoaXMuX3dyaXRhYmxlU3RhdGUgPSB0aGlzLl93cml0ZXIuX3dyaXRhYmxlU3RhdGU7XG5cbiAgICB0aGlzLl9jb3B5KFsnd3JpdGUnLCAnZW5kJ10sIHRoaXMuX3dyaXRlcik7XG4gICAgdGhpcy5fY29weShbJ3JlYWQnLCAnc2V0RW5jb2RpbmcnLCAncGlwZScsICd1bnBpcGUnXSwgdGhpcy5fcmVhZGVyKTtcblxuICAgIGZvciAoY29uc3QgbWV0aG9kIG9mIFtcbiAgICAnb24nLFxuICAgICdvbmNlJyxcbiAgICAncmVtb3ZlTGlzdGVuZXInLFxuICAgICdyZW1vdmVBbGxMaXN0ZW5lcnMnLFxuICAgICdsaXN0ZW5lcnMnXSBhc1xuICAgIGNvbnN0KSB7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICB0aGlzW21ldGhvZF0gPSAoZXYsIGZuKSA9PlxuICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgRVZFTlRTW2V2XSA/XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICBFVkVOVFNbZXZdW21ldGhvZF0oZXYsIGZuKSA6XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICBEdXBsZXgucHJvdG90eXBlW21ldGhvZF0uY2FsbCh0aGlzLCBldiwgZm4pO1xuICAgIH1cblxuICAgIGNvbnN0IHByb2Nlc3NFcnJvciA9IChlcnJvcjogRXJyb3IpID0+IHRoaXMuZW1pdCgnZXJyb3InLCBlcnJvcik7XG5cbiAgICB0aGlzLl9yZWFkZXIub24oJ2Vycm9yJywgcHJvY2Vzc0Vycm9yKTtcbiAgICB0aGlzLl93cml0ZXIub24oJ2Vycm9yJywgcHJvY2Vzc0Vycm9yKTtcbiAgfVxuXG4gIGdldCBfcmVhZGVyKCkge1xuICAgIHJldHVybiB0aGlzLnByb2Nlc3MhLnN0ZG91dDtcbiAgfVxuICBnZXQgX3dyaXRlcigpIHtcbiAgICByZXR1cm4gdGhpcy5wcm9jZXNzIS5zdGRpbjtcbiAgfVxuXG4gIHByaXZhdGUgX2NvcHkobWV0aG9kczogc3RyaW5nW10sIHRhcmdldDogdW5rbm93bikge1xuICAgIGZvciAoY29uc3QgbWV0aG9kIG9mIG1ldGhvZHMpIHtcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgIHRoaXNbbWV0aG9kXSA9IHRhcmdldFttZXRob2RdLmJpbmQodGFyZ2V0KTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgX2Rlc3Ryb3koZXJyOiBFcnJvciB8IG51bGwsIGNiOiBGRm1wZWdDYWxsYmFjazxbRXJyb3IgfCBudWxsXT4pIHtcbiAgICB0aGlzLl9jbGVhbnVwKCk7XG4gICAgaWYgKGNiKSByZXR1cm4gY2IoZXJyKTtcbiAgfVxuXG4gIHB1YmxpYyBfZmluYWwoY2I6IEZGbXBlZ0NhbGxiYWNrPFtdPikge1xuICAgIHRoaXMuX2NsZWFudXAoKTtcbiAgICBjYigpO1xuICB9XG5cbiAgcHJpdmF0ZSBfY2xlYW51cCgpIHtcbiAgICBpZiAodGhpcy5wcm9jZXNzKSB7XG4gICAgICB0aGlzLm9uY2UoJ2Vycm9yJywgKCkgPT4ge1xuXG4gICAgICAgIC8vXG4gICAgICB9KTt0aGlzLnByb2Nlc3Mua2lsbCgnU0lHS0lMTCcpO1xuICAgICAgdGhpcy5wcm9jZXNzID0gbnVsbCBhcyB1bmtub3duIGFzIENoaWxkUHJvY2Vzc1dpdGhvdXROdWxsU3RyZWFtcztcbiAgICB9XG4gIH1cbn0iLCAiZXhwb3J0IHR5cGUgRkZtcGVnTGliID1cbidmZm1wZWcnIHxcbicuL2ZmbXBlZycgfFxuJ2F2Y29udicgfFxuJy4vYXZjb252JyB8XG4nZmZtcGVnLXN0YXRpYycgfFxuJ0BmZm1wZWctaW5zdGFsbGVyL2ZmbXBlZycgfFxuJ0Bub2RlLWZmbXBlZy9ub2RlLWZmbXBlZy1pbnN0YWxsZXInIHxcbidmZm1wZWctYmluYXJpZXMnO1xuXG5leHBvcnQgdHlwZSBGRm1wZWdDYWxsYmFjazxBcmdzIGV4dGVuZHMgQXJyYXk8dW5rbm93bj4+ID0gKFxuLi4uYXJnczogQXJncylcbj0+IHVua25vd247XG5cbi8qKlxuICogRkZtcGVnIHNvdXJjZSBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRkZtcGVnU291cmNlIHtcbiAgLyoqIE5hbWUgb3IgcGF0aCBvZiB0aGUgRkZtcGVnIGV4ZWN1dGFibGUgKi9cbiAgbmFtZTogRkZtcGVnTGliO1xuICAvKiogV2hldGhlciB0aGlzIHNvdXJjZSBpcyBhIE5vZGUuanMgbW9kdWxlICovXG4gIG1vZHVsZTogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlZEZGbXBlZ1NvdXJjZSBleHRlbmRzIEZGbXBlZ1NvdXJjZSB7XG4gIHBhdGg6IHN0cmluZztcbiAgdmVyc2lvbjogc3RyaW5nO1xuICBjb21tYW5kOiBzdHJpbmc7XG4gIHJlc3VsdDogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbXBhcmVzIGFuZCB1cGRhdGVzIEZGbXBlZyBmbGFncyBhcyBuZWVkZWRcbiAqIEBwYXJhbSBvbGRGbGFncyBUaGUgb2xkIGZsYWdzXG4gKiBAcGFyYW0gbmV3RmxhZ3MgVGhlIG5ldyBmbGFnc1xuICogQHJldHVybnMgVGhlIHVwZGF0ZWQgZmxhZ3NcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoYW5nZUZGbXBlZ0ZsYWdzKG9sZEZsYWdzOiBzdHJpbmdbXSwgbmV3RmxhZ3M6IHN0cmluZ1tdKSB7XG4gIGNvbnN0IHVwZGF0ZWRGbGFncyA9IFsuLi5vbGRGbGFnc107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdGbGFncy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGtleSA9IG5ld0ZsYWdzW2ldO1xuICAgIGNvbnN0IHZhbHVlID0gbmV3RmxhZ3NbaSArIDFdO1xuXG4gICAgY29uc3Qgb2xkSW5kZXggPSB1cGRhdGVkRmxhZ3MuaW5kZXhPZihrZXkpO1xuXG4gICAgaWYgKG9sZEluZGV4ICE9PSAtMSkge1xuICAgICAgaWYgKHZhbHVlICYmICF2YWx1ZS5zdGFydHNXaXRoKCctJykpIHtcbiAgICAgICAgdXBkYXRlZEZsYWdzW29sZEluZGV4ICsgMV0gPSB2YWx1ZTtcbiAgICAgICAgaSsrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXBkYXRlZEZsYWdzLnNwbGljZShvbGRJbmRleCwgMSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh2YWx1ZSAmJiAhdmFsdWUuc3RhcnRzV2l0aCgnLScpKSB7XG4gICAgICAgIHVwZGF0ZWRGbGFncy5wdXNoKGtleSwgdmFsdWUpO1xuICAgICAgICBpKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1cGRhdGVkRmxhZ3MucHVzaChrZXkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB1cGRhdGVkRmxhZ3M7XG59IiwgIlxuXG5cblxuXG5cbmV4cG9ydCBjb25zdCB2ZXJzaW9uID0gLyogQF9fTUFDUk9fXyBnZXRWZXJzaW9uICovXCI3LjIuMFwiOyJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7O0FDQUEsZ0NBSUE7QUFDQSx5QkFBc0M7QUFRdEMsSUFBTSxnQkFBZ0I7QUFFdEIsSUFBTSxvQkFBb0Isd0JBQUMsTUFBYyxnQkFBd0I7QUFDL0QsTUFBSSxDQUFDLEtBQU0sT0FBTSxJQUFJLE1BQU0scUJBQXFCLFdBQVcsRUFBRTtBQUM3RCxTQUFPO0FBQ1QsR0FIMEI7QUFLbkIsSUFBTSxVQUFOLE1BQU0sZ0JBQWUsMEJBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUEwSjFCLFlBQVksVUFBeUIsQ0FBQyxHQUFHO0FBQzlDLFVBQU0sT0FBTztBQXZCZjtBQUFBO0FBQUE7QUFBQSx3QkFBTztBQXlCTCxTQUFLLFVBQVUsUUFBTyxNQUFNLE9BQU87QUFFbkMsVUFBTSxTQUFTO0FBQUEsTUFDYixVQUFVLEtBQUs7QUFBQSxNQUNmLE1BQU0sS0FBSztBQUFBLE1BQ1gsS0FBSyxLQUFLO0FBQUEsTUFDVixRQUFRLEtBQUs7QUFBQSxNQUNiLFFBQVEsS0FBSztBQUFBLE1BQ2IsT0FBTyxLQUFLO0FBQUEsSUFDZDtBQUdBLFNBQUssaUJBQWlCLEtBQUssUUFBUTtBQUVuQyxTQUFLLGlCQUFpQixLQUFLLFFBQVE7QUFFbkMsU0FBSyxNQUFNLENBQUMsU0FBUyxLQUFLLEdBQUcsS0FBSyxPQUFPO0FBQ3pD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