UNPKG

@tricoteuses/assemblee

Version:

Retrieve, clean up & handle French Assemblée nationale's open data

276 lines (274 loc) 48.6 kB
import commandLineArgs from "command-line-args"; import fs from "fs-extra"; import path from "path"; import { cleanActeur, cleanAmendement, cleanDocumentOrDivision, cleanDossierParlementaire, cleanOrgane, cleanReunion, cleanScrutin, cleanQuestion, cleanCompteRendu } from "../cleaners/index.mjs"; import { datasets, EnabledDatasets, getEnabledDatasets, filterByLegislature } from "../datasets.mjs"; import { downloadAndParse } from "./retrieve_documents.mjs"; import { existingDateToJson, patchedDateToJson } from "../dates.mjs"; import { walkDir } from "../file_systems.mjs"; import * as git from "../git.mjs"; import { Convert as ActeursEtOrganesConvert } from "../types/acteurs_et_organes.mjs"; import { Convert as AgendasConvert } from "../types/agendas.mjs"; import { Convert as AmendementsConvert } from "../types/amendements.mjs"; import { Convert as DossiersLegislatifsConvert } from "../types/dossiers_legislatifs.mjs"; import { Convert as ScrutinsConvert } from "../types/scrutins.mjs"; import { Convert as QuestionsConvert } from "../types/questions.mjs"; import { Convert as ComptesRendusConvert } from "../types/debats.mjs"; import { cloneOption, commitOption, remoteOption, legislatureOption, categoriesOption, dataDirDefaultOption, silentOption, verboseOption, pullOption, fetchDocumentsOption, parseDocumentsOption, documentFormatOption } from "./shared/cli_helpers.mjs"; function parseArgs(argv) { const optionsDefinitions = [cloneOption, commitOption, remoteOption, legislatureOption, categoriesOption, silentOption, verboseOption, dataDirDefaultOption, pullOption, fetchDocumentsOption, parseDocumentsOption, documentFormatOption, { alias: "d", help: "single dataset to reorganize", name: "dataset", type: String }, { help: "do not reset --hard after commit to save I/O if the working tree is to be discarded", name: "no-reset-after-commit", type: Boolean }, { alias: "V", help: "don't validate data", name: "no-validate", type: Boolean }]; const options = commandLineArgs(optionsDefinitions, { argv: argv }); return options; } function cloneGit(gitGroupUrl, datasetName, dataDir) { git.clone(gitGroupUrl, `${datasetName}_nettoye`, dataDir); } function commitGit(datasetCleanDir, options, exitCode, subdirectories) { if (options.commit) { const errorCode = git.commitAndPush(datasetCleanDir, "Nouvelle moisson", options.remote); if (exitCode === 10 && errorCode !== 10 || exitCode === 0 && errorCode !== 0 && errorCode !== 10) { exitCode = errorCode; } } if (commitAndPushUid(datasetCleanDir, options, subdirectories) && (exitCode === 0 || exitCode === 10)) { exitCode = 1; } return exitCode; } function cleanAndValidateData(data, cleaner, fromJson, toJson, noValidate) { cleaner(data); if (typeof data === "object" && Object.keys(data).length === 0) { // By convention: an empty object must be deleted. return null; } const jsonData = JSON.stringify(data, null, 2); if (!noValidate) { return jsonData; } else { const validatedData = fromJson(jsonData); return toJson(validatedData); } } async function processFiles(datasetRawDir, datasetCleanDir, walkDirParams, cleaner, dataConverter, options, postProcessor) { for (const filePathArray of walkDir(datasetRawDir, walkDirParams)) { const filename = filePathArray[filePathArray.length - 1]; if (!filename.endsWith(".json")) continue; const rawFilePath = path.join(datasetRawDir, ...filePathArray); const rawJson = fs.readFileSync(rawFilePath, { encoding: "utf8" }); if (options.verbose) console.log(`Cleaning file: ${rawFilePath}...`); const data = JSON.parse(rawJson); const validateData = !options["no-validate"]; const cleanJson = cleanAndValidateData(data, cleaner, dataConverter.fromJson, dataConverter.toJson, validateData); if (cleanJson !== null) { const cleanFilePath = path.join(datasetCleanDir, ...filePathArray); fs.ensureDirSync(path.dirname(cleanFilePath)); fs.writeFileSync(cleanFilePath, cleanJson, { encoding: "utf8" }); if (postProcessor) { await postProcessor(data, datasetCleanDir, options); } } } } async function cleanReorganizedData(options) { const dataDir = options.dataDir; Date.prototype.toJSON = patchedDateToJson; let exitCode = options.commit ? 10 : 0; const gitGroupUrl = options.clone?.trim().replace(/\/+$/, ""); const enabledDatasets = getEnabledDatasets(options.categories); let chosenDatasets = filterByLegislature(datasets, options.legislature); if (enabledDatasets & EnabledDatasets.ActeursEtOrganes) { for (const dataset of chosenDatasets.acteursEtOrganes) { const datasetName = path.basename(dataset.filename, ".json"); if (options.dataset && datasetName !== options.dataset) { continue; } cloneGit(gitGroupUrl, datasetName, dataDir); const datasetRawDir = path.join(dataDir, datasetName); const datasetCleanDir = `${datasetRawDir}_nettoye`; if (options.pull) { git.resetAndPull(datasetCleanDir); } analyzeAndRemove(datasetName, options); await processFiles(datasetRawDir, datasetCleanDir, ["acteurs"], cleanActeur, { fromJson: ActeursEtOrganesConvert.toActeur, toJson: ActeursEtOrganesConvert.acteurToJson }, options); await processFiles(datasetRawDir, datasetCleanDir, ["organes"], cleanOrgane, { fromJson: ActeursEtOrganesConvert.toOrgane, toJson: ActeursEtOrganesConvert.organeToJson }, options); exitCode = commitGit(datasetCleanDir, options, exitCode, ["acteurs", "organes"]); } } if (enabledDatasets & EnabledDatasets.Agendas) { for (const dataset of chosenDatasets.agendas) { const datasetName = path.basename(dataset.filename, ".json"); if (options.dataset && datasetName !== options.dataset) { continue; } cloneGit(gitGroupUrl, datasetName, dataDir); analyzeAndRemove(datasetName, options); const datasetRawDir = path.join(dataDir, datasetName); const datasetCleanDir = `${datasetRawDir}_nettoye`; await processFiles(datasetRawDir, datasetCleanDir, [], cleanReunion, { fromJson: AgendasConvert.toReunion, toJson: AgendasConvert.reunionToJson }, options); exitCode = commitGit(datasetCleanDir, options, exitCode, ["."]); } } if (enabledDatasets & EnabledDatasets.Amendements) { for (const dataset of chosenDatasets.amendements) { const datasetName = path.basename(dataset.filename, ".json"); if (options.dataset && datasetName !== options.dataset) { continue; } cloneGit(gitGroupUrl, datasetName, dataDir); analyzeAndRemove(datasetName, options); const datasetRawDir = path.join(dataDir, datasetName); const datasetCleanDir = `${datasetRawDir}_nettoye`; await processFiles(datasetRawDir, datasetCleanDir, [], cleanAmendement, { fromJson: AmendementsConvert.toAmendement, toJson: AmendementsConvert.amendementToJson }, options); exitCode = commitGit(datasetCleanDir, options, exitCode, ["."]); } } if (enabledDatasets & EnabledDatasets.DossiersLegislatifs) { for (const dataset of chosenDatasets.dossiersLegislatifs) { const datasetName = path.basename(dataset.filename, ".json"); if (options.dataset && datasetName !== options.dataset) { continue; } cloneGit(gitGroupUrl, datasetName, dataDir); analyzeAndRemove(datasetName, options); const datasetRawDir = path.join(dataDir, datasetName); const datasetCleanDir = `${datasetRawDir}_nettoye`; await processFiles(datasetRawDir, datasetCleanDir, ["documents"], cleanDocumentOrDivision, { fromJson: DossiersLegislatifsConvert.toDocument, toJson: DossiersLegislatifsConvert.documentToJson }, options, downloadAndParse); await processFiles(datasetRawDir, datasetCleanDir, ["dossiers"], cleanDossierParlementaire, { fromJson: DossiersLegislatifsConvert.toDossierParlementaire, toJson: DossiersLegislatifsConvert.dossierParlementaireToJson }, options); exitCode = commitGit(datasetCleanDir, options, exitCode, ["documents", "dossiers"]); } } if (enabledDatasets & EnabledDatasets.Scrutins) { for (const dataset of chosenDatasets.scrutins) { const datasetName = path.basename(dataset.filename, ".json"); if (options.dataset && datasetName !== options.dataset) { continue; } cloneGit(gitGroupUrl, datasetName, dataDir); analyzeAndRemove(datasetName, options); const datasetRawDir = path.join(dataDir, datasetName); const datasetCleanDir = `${datasetRawDir}_nettoye`; await processFiles(datasetRawDir, datasetCleanDir, [], cleanScrutin, { fromJson: ScrutinsConvert.toScrutin, toJson: ScrutinsConvert.scrutinToJson }, options); exitCode = commitGit(datasetCleanDir, options, exitCode, ["."]); } } if (enabledDatasets & EnabledDatasets.Questions) { for (const dataset of datasets.questions) { const datasetName = path.basename(dataset.filename, ".json"); if (options.dataset && datasetName !== options.dataset) { continue; } cloneGit(gitGroupUrl, datasetName, dataDir); analyzeAndRemove(datasetName, options); const datasetRawDir = path.join(dataDir, datasetName); const datasetCleanDir = `${datasetRawDir}_nettoye`; await processFiles(datasetRawDir, datasetCleanDir, [], cleanQuestion, { fromJson: QuestionsConvert.toQuestion, toJson: QuestionsConvert.questionToJson }, options); exitCode = commitGit(datasetCleanDir, options, exitCode, ["."]); } } if (enabledDatasets & EnabledDatasets.ComptesRendusSeances) { for (const dataset of datasets.comptesRendusSeances) { const datasetName = path.basename(dataset.filename, ".xml"); if (options.dataset && datasetName !== options.dataset) { continue; } cloneGit(gitGroupUrl, datasetName, dataDir); analyzeAndRemove(datasetName, options); const datasetRawDir = path.join(dataDir, datasetName); const datasetCleanDir = `${datasetRawDir}_nettoye`; await processFiles(datasetRawDir, datasetCleanDir, [], cleanCompteRendu, { fromJson: ComptesRendusConvert.toCompteRendu, toJson: ComptesRendusConvert.compteRenduToJson }, options); exitCode = commitGit(datasetCleanDir, options, exitCode, ["."]); } } // Restore standard conversion of dates to JSON. Date.prototype.toJSON = existingDateToJson; if (!options.silent) { console.log("Finished !"); } return exitCode; } function analyzeAndRemove(datasetName, options) { const dataDir = options.dataDir; const datasetRawDir = path.join(dataDir, datasetName); const datasetCleanDir = `${datasetRawDir}_nettoye`; if (!options.silent) { console.log(`Cleaning directory: ${datasetCleanDir}…`); } fs.ensureDirSync(datasetCleanDir); for (const filename of fs.readdirSync(datasetCleanDir)) { if (filename[0] === ".") { continue; } const pathname = path.join(datasetCleanDir, filename); fs.removeSync(pathname); } } function commitAndPushUid(repositoryDir, options, subdirectories) { let error = false; if (options.commit) { git.uidBranchUpdate(repositoryDir, subdirectories, options["no-reset-after-commit"]); for (const remote of options.remote || []) { try { git.run(repositoryDir, `push --quiet ${remote} uid:uid`); } catch (childProcess) { error = true; } } } return error; } function main(argv) { const options = parseArgs(argv); return cleanReorganizedData(options); } /* istanbul ignore if */ if (process.argv[1].endsWith("clean_reorganized_data.ts")) { main(process.argv).then(process.exit); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjb21tYW5kTGluZUFyZ3MiLCJmcyIsInBhdGgiLCJjbGVhbkFjdGV1ciIsImNsZWFuQW1lbmRlbWVudCIsImNsZWFuRG9jdW1lbnRPckRpdmlzaW9uIiwiY2xlYW5Eb3NzaWVyUGFybGVtZW50YWlyZSIsImNsZWFuT3JnYW5lIiwiY2xlYW5SZXVuaW9uIiwiY2xlYW5TY3J1dGluIiwiY2xlYW5RdWVzdGlvbiIsImNsZWFuQ29tcHRlUmVuZHUiLCJkYXRhc2V0cyIsIkVuYWJsZWREYXRhc2V0cyIsImdldEVuYWJsZWREYXRhc2V0cyIsImZpbHRlckJ5TGVnaXNsYXR1cmUiLCJkb3dubG9hZEFuZFBhcnNlIiwiZXhpc3RpbmdEYXRlVG9Kc29uIiwicGF0Y2hlZERhdGVUb0pzb24iLCJ3YWxrRGlyIiwiZ2l0IiwiQ29udmVydCIsIkFjdGV1cnNFdE9yZ2FuZXNDb252ZXJ0IiwiQWdlbmRhc0NvbnZlcnQiLCJBbWVuZGVtZW50c0NvbnZlcnQiLCJEb3NzaWVyc0xlZ2lzbGF0aWZzQ29udmVydCIsIlNjcnV0aW5zQ29udmVydCIsIlF1ZXN0aW9uc0NvbnZlcnQiLCJDb21wdGVzUmVuZHVzQ29udmVydCIsImNsb25lT3B0aW9uIiwiY29tbWl0T3B0aW9uIiwicmVtb3RlT3B0aW9uIiwibGVnaXNsYXR1cmVPcHRpb24iLCJjYXRlZ29yaWVzT3B0aW9uIiwiZGF0YURpckRlZmF1bHRPcHRpb24iLCJzaWxlbnRPcHRpb24iLCJ2ZXJib3NlT3B0aW9uIiwicHVsbE9wdGlvbiIsImZldGNoRG9jdW1lbnRzT3B0aW9uIiwicGFyc2VEb2N1bWVudHNPcHRpb24iLCJkb2N1bWVudEZvcm1hdE9wdGlvbiIsInBhcnNlQXJncyIsImFyZ3YiLCJvcHRpb25zRGVmaW5pdGlvbnMiLCJhbGlhcyIsImhlbHAiLCJuYW1lIiwidHlwZSIsIlN0cmluZyIsIkJvb2xlYW4iLCJvcHRpb25zIiwiY2xvbmVHaXQiLCJnaXRHcm91cFVybCIsImRhdGFzZXROYW1lIiwiZGF0YURpciIsImNsb25lIiwiY29tbWl0R2l0IiwiZGF0YXNldENsZWFuRGlyIiwiZXhpdENvZGUiLCJzdWJkaXJlY3RvcmllcyIsImNvbW1pdCIsImVycm9yQ29kZSIsImNvbW1pdEFuZFB1c2giLCJyZW1vdGUiLCJjb21taXRBbmRQdXNoVWlkIiwiY2xlYW5BbmRWYWxpZGF0ZURhdGEiLCJkYXRhIiwiY2xlYW5lciIsImZyb21Kc29uIiwidG9Kc29uIiwibm9WYWxpZGF0ZSIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJqc29uRGF0YSIsIkpTT04iLCJzdHJpbmdpZnkiLCJ2YWxpZGF0ZWREYXRhIiwicHJvY2Vzc0ZpbGVzIiwiZGF0YXNldFJhd0RpciIsIndhbGtEaXJQYXJhbXMiLCJkYXRhQ29udmVydGVyIiwicG9zdFByb2Nlc3NvciIsImZpbGVQYXRoQXJyYXkiLCJmaWxlbmFtZSIsImVuZHNXaXRoIiwicmF3RmlsZVBhdGgiLCJqb2luIiwicmF3SnNvbiIsInJlYWRGaWxlU3luYyIsImVuY29kaW5nIiwidmVyYm9zZSIsImNvbnNvbGUiLCJsb2ciLCJwYXJzZSIsInZhbGlkYXRlRGF0YSIsImNsZWFuSnNvbiIsImNsZWFuRmlsZVBhdGgiLCJlbnN1cmVEaXJTeW5jIiwiZGlybmFtZSIsIndyaXRlRmlsZVN5bmMiLCJjbGVhblJlb3JnYW5pemVkRGF0YSIsIkRhdGUiLCJwcm90b3R5cGUiLCJ0b0pTT04iLCJ0cmltIiwicmVwbGFjZSIsImVuYWJsZWREYXRhc2V0cyIsImNhdGVnb3JpZXMiLCJjaG9zZW5EYXRhc2V0cyIsImxlZ2lzbGF0dXJlIiwiQWN0ZXVyc0V0T3JnYW5lcyIsImRhdGFzZXQiLCJhY3RldXJzRXRPcmdhbmVzIiwiYmFzZW5hbWUiLCJwdWxsIiwicmVzZXRBbmRQdWxsIiwiYW5hbHl6ZUFuZFJlbW92ZSIsInRvQWN0ZXVyIiwiYWN0ZXVyVG9Kc29uIiwidG9PcmdhbmUiLCJvcmdhbmVUb0pzb24iLCJBZ2VuZGFzIiwiYWdlbmRhcyIsInRvUmV1bmlvbiIsInJldW5pb25Ub0pzb24iLCJBbWVuZGVtZW50cyIsImFtZW5kZW1lbnRzIiwidG9BbWVuZGVtZW50IiwiYW1lbmRlbWVudFRvSnNvbiIsIkRvc3NpZXJzTGVnaXNsYXRpZnMiLCJkb3NzaWVyc0xlZ2lzbGF0aWZzIiwidG9Eb2N1bWVudCIsImRvY3VtZW50VG9Kc29uIiwidG9Eb3NzaWVyUGFybGVtZW50YWlyZSIsImRvc3NpZXJQYXJsZW1lbnRhaXJlVG9Kc29uIiwiU2NydXRpbnMiLCJzY3J1dGlucyIsInRvU2NydXRpbiIsInNjcnV0aW5Ub0pzb24iLCJRdWVzdGlvbnMiLCJxdWVzdGlvbnMiLCJ0b1F1ZXN0aW9uIiwicXVlc3Rpb25Ub0pzb24iLCJDb21wdGVzUmVuZHVzU2VhbmNlcyIsImNvbXB0ZXNSZW5kdXNTZWFuY2VzIiwidG9Db21wdGVSZW5kdSIsImNvbXB0ZVJlbmR1VG9Kc29uIiwic2lsZW50IiwicmVhZGRpclN5bmMiLCJwYXRobmFtZSIsInJlbW92ZVN5bmMiLCJyZXBvc2l0b3J5RGlyIiwiZXJyb3IiLCJ1aWRCcmFuY2hVcGRhdGUiLCJydW4iLCJjaGlsZFByb2Nlc3MiLCJtYWluIiwicHJvY2VzcyIsInRoZW4iLCJleGl0Il0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NjcmlwdHMvY2xlYW5fcmVvcmdhbml6ZWRfZGF0YS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY29tbWFuZExpbmVBcmdzIGZyb20gXCJjb21tYW5kLWxpbmUtYXJnc1wiXG5pbXBvcnQgZnMgZnJvbSBcImZzLWV4dHJhXCJcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCJcbmltcG9ydCB7XG4gIGNsZWFuQWN0ZXVyLFxuICBjbGVhbkFtZW5kZW1lbnQsXG4gIGNsZWFuRG9jdW1lbnRPckRpdmlzaW9uLFxuICBjbGVhbkRvc3NpZXJQYXJsZW1lbnRhaXJlLFxuICBjbGVhbk9yZ2FuZSxcbiAgY2xlYW5SZXVuaW9uLFxuICBjbGVhblNjcnV0aW4sXG4gIGNsZWFuUXVlc3Rpb24sXG4gIGNsZWFuQ29tcHRlUmVuZHUsXG59IGZyb20gXCIuLi9jbGVhbmVyc1wiXG5pbXBvcnQge1xuICBkYXRhc2V0cyxcbiAgRW5hYmxlZERhdGFzZXRzLFxuICBnZXRFbmFibGVkRGF0YXNldHMsXG4gIGZpbHRlckJ5TGVnaXNsYXR1cmUsXG59IGZyb20gXCIuLi9kYXRhc2V0c1wiXG5pbXBvcnQgeyBkb3dubG9hZEFuZFBhcnNlIH0gZnJvbSBcIi4vcmV0cmlldmVfZG9jdW1lbnRzXCJcbmltcG9ydCB7IGV4aXN0aW5nRGF0ZVRvSnNvbiwgcGF0Y2hlZERhdGVUb0pzb24gfSBmcm9tIFwiLi4vZGF0ZXNcIlxuaW1wb3J0IHsgd2Fsa0RpciB9IGZyb20gXCIuLi9maWxlX3N5c3RlbXNcIlxuaW1wb3J0ICogYXMgZ2l0IGZyb20gXCIuLi9naXRcIlxuaW1wb3J0IHtcbiAgQWN0ZXVyLFxuICBDb252ZXJ0IGFzIEFjdGV1cnNFdE9yZ2FuZXNDb252ZXJ0LFxuICBPcmdhbmUsXG59IGZyb20gXCIuLi90eXBlcy9hY3RldXJzX2V0X29yZ2FuZXNcIlxuaW1wb3J0IHsgQ29udmVydCBhcyBBZ2VuZGFzQ29udmVydCwgUmV1bmlvbiB9IGZyb20gXCIuLi90eXBlcy9hZ2VuZGFzXCJcbmltcG9ydCB7IEFtZW5kZW1lbnQsIENvbnZlcnQgYXMgQW1lbmRlbWVudHNDb252ZXJ0IH0gZnJvbSBcIi4uL3R5cGVzL2FtZW5kZW1lbnRzXCJcbmltcG9ydCB7XG4gIENvbnZlcnQgYXMgRG9zc2llcnNMZWdpc2xhdGlmc0NvbnZlcnQsXG4gIERvY3VtZW50LFxuICBEb3NzaWVyUGFybGVtZW50YWlyZSxcbn0gZnJvbSBcIi4uL3R5cGVzL2Rvc3NpZXJzX2xlZ2lzbGF0aWZzXCJcbmltcG9ydCB7IENvbnZlcnQgYXMgU2NydXRpbnNDb252ZXJ0LCBTY3J1dGluIH0gZnJvbSBcIi4uL3R5cGVzL3NjcnV0aW5zXCJcbmltcG9ydCB7IENvbnZlcnQgYXMgUXVlc3Rpb25zQ29udmVydCwgUXVlc3Rpb24gfSBmcm9tIFwiLi4vdHlwZXMvcXVlc3Rpb25zXCJcbmltcG9ydCB7IENvbnZlcnQgYXMgQ29tcHRlc1JlbmR1c0NvbnZlcnQsIENvbXB0ZVJlbmR1IH0gZnJvbSBcIi4uL3R5cGVzL2RlYmF0c1wiXG5pbXBvcnQge1xuICBjbG9uZU9wdGlvbixcbiAgY29tbWl0T3B0aW9uLFxuICByZW1vdGVPcHRpb24sXG4gIGxlZ2lzbGF0dXJlT3B0aW9uLFxuICBjYXRlZ29yaWVzT3B0aW9uLFxuICBkYXRhRGlyRGVmYXVsdE9wdGlvbixcbiAgc2lsZW50T3B0aW9uLFxuICB2ZXJib3NlT3B0aW9uLFxuICBwdWxsT3B0aW9uLFxuICBmZXRjaERvY3VtZW50c09wdGlvbixcbiAgcGFyc2VEb2N1bWVudHNPcHRpb24sXG4gIGRvY3VtZW50Rm9ybWF0T3B0aW9uLFxufSBmcm9tIFwiLi9zaGFyZWQvY2xpX2hlbHBlcnNcIlxuXG5mdW5jdGlvbiBwYXJzZUFyZ3MoYXJndjogc3RyaW5nW10pOiBhbnkge1xuICBjb25zdCBvcHRpb25zRGVmaW5pdGlvbnMgPSBbXG4gICAgY2xvbmVPcHRpb24sXG4gICAgY29tbWl0T3B0aW9uLFxuICAgIHJlbW90ZU9wdGlvbixcbiAgICBsZWdpc2xhdHVyZU9wdGlvbixcbiAgICBjYXRlZ29yaWVzT3B0aW9uLFxuICAgIHNpbGVudE9wdGlvbixcbiAgICB2ZXJib3NlT3B0aW9uLFxuICAgIGRhdGFEaXJEZWZhdWx0T3B0aW9uLFxuICAgIHB1bGxPcHRpb24sXG4gICAgZmV0Y2hEb2N1bWVudHNPcHRpb24sXG4gICAgcGFyc2VEb2N1bWVudHNPcHRpb24sXG4gICAgZG9jdW1lbnRGb3JtYXRPcHRpb24sXG4gICAge1xuICAgICAgYWxpYXM6IFwiZFwiLFxuICAgICAgaGVscDogXCJzaW5nbGUgZGF0YXNldCB0byByZW9yZ2FuaXplXCIsXG4gICAgICBuYW1lOiBcImRhdGFzZXRcIixcbiAgICAgIHR5cGU6IFN0cmluZyxcbiAgICB9LFxuICAgIHtcbiAgICAgIGhlbHA6IFwiZG8gbm90IHJlc2V0IC0taGFyZCBhZnRlciBjb21taXQgdG8gc2F2ZSBJL08gaWYgdGhlIHdvcmtpbmcgdHJlZSBpcyB0byBiZSBkaXNjYXJkZWRcIixcbiAgICAgIG5hbWU6IFwibm8tcmVzZXQtYWZ0ZXItY29tbWl0XCIsXG4gICAgICB0eXBlOiBCb29sZWFuLFxuICAgIH0sXG4gICAge1xuICAgICAgYWxpYXM6IFwiVlwiLFxuICAgICAgaGVscDogXCJkb24ndCB2YWxpZGF0ZSBkYXRhXCIsXG4gICAgICBuYW1lOiBcIm5vLXZhbGlkYXRlXCIsXG4gICAgICB0eXBlOiBCb29sZWFuLFxuICAgIH0sXG4gIF1cbiAgY29uc3Qgb3B0aW9ucyA9IGNvbW1hbmRMaW5lQXJncyhvcHRpb25zRGVmaW5pdGlvbnMsIHtcbiAgICBhcmd2OiBhcmd2LFxuICB9KVxuICByZXR1cm4gb3B0aW9uc1xufVxuXG5mdW5jdGlvbiBjbG9uZUdpdChcbiAgZ2l0R3JvdXBVcmw6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgZGF0YXNldE5hbWU6IHN0cmluZyxcbiAgZGF0YURpcjogc3RyaW5nLFxuKTogdm9pZCB7XG4gIGdpdC5jbG9uZShnaXRHcm91cFVybCwgYCR7ZGF0YXNldE5hbWV9X25ldHRveWVgLCBkYXRhRGlyKVxufVxuXG5mdW5jdGlvbiBjb21taXRHaXQoXG4gIGRhdGFzZXRDbGVhbkRpcjogc3RyaW5nLFxuICBvcHRpb25zOiBhbnksXG4gIGV4aXRDb2RlOiBudW1iZXIsXG4gIHN1YmRpcmVjdG9yaWVzOiBhbnksXG4pOiBudW1iZXIge1xuICBpZiAob3B0aW9ucy5jb21taXQpIHtcbiAgICBjb25zdCBlcnJvckNvZGUgPSBnaXQuY29tbWl0QW5kUHVzaChcbiAgICAgIGRhdGFzZXRDbGVhbkRpcixcbiAgICAgIFwiTm91dmVsbGUgbW9pc3NvblwiLFxuICAgICAgb3B0aW9ucy5yZW1vdGUsXG4gICAgKVxuICAgIGlmIChcbiAgICAgIChleGl0Q29kZSA9PT0gMTAgJiYgZXJyb3JDb2RlICE9PSAxMCkgfHxcbiAgICAgIChleGl0Q29kZSA9PT0gMCAmJiBlcnJvckNvZGUgIT09IDAgJiYgZXJyb3JDb2RlICE9PSAxMClcbiAgICApIHtcbiAgICAgIGV4aXRDb2RlID0gZXJyb3JDb2RlXG4gICAgfVxuICB9XG4gIGlmIChcbiAgICBjb21taXRBbmRQdXNoVWlkKGRhdGFzZXRDbGVhbkRpciwgb3B0aW9ucywgc3ViZGlyZWN0b3JpZXMpICYmXG4gICAgKGV4aXRDb2RlID09PSAwIHx8IGV4aXRDb2RlID09PSAxMClcbiAgKSB7XG4gICAgZXhpdENvZGUgPSAxXG4gIH1cbiAgcmV0dXJuIGV4aXRDb2RlXG59XG5cbmZ1bmN0aW9uIGNsZWFuQW5kVmFsaWRhdGVEYXRhPFQ+KFxuICBkYXRhOiBhbnksXG4gIGNsZWFuZXI6IChkYXRhOiBUKSA9PiB2b2lkLFxuICBmcm9tSnNvbjogKGpzb246IHN0cmluZykgPT4gVCxcbiAgdG9Kc29uOiAoZGF0YTogVCkgPT4gc3RyaW5nLFxuICBub1ZhbGlkYXRlOiBCb29sZWFuLFxuKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNsZWFuZXIoZGF0YSlcbiAgaWYgKHR5cGVvZiBkYXRhID09PSBcIm9iamVjdFwiICYmIE9iamVjdC5rZXlzKGRhdGEpLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIEJ5IGNvbnZlbnRpb246IGFuIGVtcHR5IG9iamVjdCBtdXN0IGJlIGRlbGV0ZWQuXG4gICAgcmV0dXJuIG51bGxcbiAgfVxuICBjb25zdCBqc29uRGF0YSA9IEpTT04uc3RyaW5naWZ5KGRhdGEsIG51bGwsIDIpXG4gIGlmICghbm9WYWxpZGF0ZSkge1xuICAgIHJldHVybiBqc29uRGF0YVxuICB9IGVsc2Uge1xuICAgIGNvbnN0IHZhbGlkYXRlZERhdGE6IFQgPSBmcm9tSnNvbihqc29uRGF0YSlcbiAgICByZXR1cm4gdG9Kc29uKHZhbGlkYXRlZERhdGEpXG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc0ZpbGVzPFQ+KFxuICBkYXRhc2V0UmF3RGlyOiBzdHJpbmcsXG4gIGRhdGFzZXRDbGVhbkRpcjogc3RyaW5nLFxuICB3YWxrRGlyUGFyYW1zOiBhbnlbXSxcbiAgY2xlYW5lcjogYW55LFxuICBkYXRhQ29udmVydGVyOiB7IGZyb21Kc29uOiBhbnk7IHRvSnNvbjogYW55IH0sXG4gIG9wdGlvbnM6IGFueSxcbiAgcG9zdFByb2Nlc3Nvcj86IGFueSxcbik6IFByb21pc2U8dm9pZD4ge1xuICBmb3IgKGNvbnN0IGZpbGVQYXRoQXJyYXkgb2Ygd2Fsa0RpcihkYXRhc2V0UmF3RGlyLCB3YWxrRGlyUGFyYW1zKSkge1xuICAgIGNvbnN0IGZpbGVuYW1lID0gZmlsZVBhdGhBcnJheVtmaWxlUGF0aEFycmF5Lmxlbmd0aCAtIDFdXG4gICAgaWYgKCFmaWxlbmFtZS5lbmRzV2l0aChcIi5qc29uXCIpKSBjb250aW51ZVxuICAgIGNvbnN0IHJhd0ZpbGVQYXRoID0gcGF0aC5qb2luKGRhdGFzZXRSYXdEaXIsIC4uLmZpbGVQYXRoQXJyYXkpXG4gICAgY29uc3QgcmF3SnNvbiA9IGZzLnJlYWRGaWxlU3luYyhyYXdGaWxlUGF0aCwgeyBlbmNvZGluZzogXCJ1dGY4XCIgfSlcbiAgICBpZiAob3B0aW9ucy52ZXJib3NlKSBjb25zb2xlLmxvZyhgQ2xlYW5pbmcgZmlsZTogJHtyYXdGaWxlUGF0aH0uLi5gKVxuICAgIGNvbnN0IGRhdGEgPSBKU09OLnBhcnNlKHJhd0pzb24pXG4gICAgY29uc3QgdmFsaWRhdGVEYXRhID0gIW9wdGlvbnNbXCJuby12YWxpZGF0ZVwiXVxuICAgIGNvbnN0IGNsZWFuSnNvbiA9IGNsZWFuQW5kVmFsaWRhdGVEYXRhPFQ+KFxuICAgICAgZGF0YSxcbiAgICAgIGNsZWFuZXIsXG4gICAgICBkYXRhQ29udmVydGVyLmZyb21Kc29uLFxuICAgICAgZGF0YUNvbnZlcnRlci50b0pzb24sXG4gICAgICB2YWxpZGF0ZURhdGEsXG4gICAgKVxuXG4gICAgaWYgKGNsZWFuSnNvbiAhPT0gbnVsbCkge1xuICAgICAgY29uc3QgY2xlYW5GaWxlUGF0aCA9IHBhdGguam9pbihkYXRhc2V0Q2xlYW5EaXIsIC4uLmZpbGVQYXRoQXJyYXkpXG4gICAgICBmcy5lbnN1cmVEaXJTeW5jKHBhdGguZGlybmFtZShjbGVhbkZpbGVQYXRoKSlcbiAgICAgIGZzLndyaXRlRmlsZVN5bmMoY2xlYW5GaWxlUGF0aCwgY2xlYW5Kc29uLCB7IGVuY29kaW5nOiBcInV0ZjhcIiB9KVxuXG4gICAgICBpZiAocG9zdFByb2Nlc3Nvcikge1xuICAgICAgICBhd2FpdCBwb3N0UHJvY2Vzc29yKGRhdGEsIGRhdGFzZXRDbGVhbkRpciwgb3B0aW9ucylcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gY2xlYW5SZW9yZ2FuaXplZERhdGEob3B0aW9uczogYW55KTogUHJvbWlzZTxudW1iZXI+IHtcbiAgY29uc3QgZGF0YURpcjogc3RyaW5nID0gb3B0aW9ucy5kYXRhRGlyXG4gIERhdGUucHJvdG90eXBlLnRvSlNPTiA9IHBhdGNoZWREYXRlVG9Kc29uXG4gIGxldCBleGl0Q29kZSA9IG9wdGlvbnMuY29tbWl0ID8gMTAgOiAwXG4gIGNvbnN0IGdpdEdyb3VwVXJsID0gb3B0aW9ucy5jbG9uZT8udHJpbSgpLnJlcGxhY2UoL1xcLyskLywgXCJcIilcbiAgY29uc3QgZW5hYmxlZERhdGFzZXRzID0gZ2V0RW5hYmxlZERhdGFzZXRzKG9wdGlvbnMuY2F0ZWdvcmllcylcbiAgbGV0IGNob3NlbkRhdGFzZXRzID0gZmlsdGVyQnlMZWdpc2xhdHVyZShkYXRhc2V0cywgb3B0aW9ucy5sZWdpc2xhdHVyZSlcblxuICBpZiAoZW5hYmxlZERhdGFzZXRzICYgRW5hYmxlZERhdGFzZXRzLkFjdGV1cnNFdE9yZ2FuZXMpIHtcbiAgICBmb3IgKGNvbnN0IGRhdGFzZXQgb2YgY2hvc2VuRGF0YXNldHMuYWN0ZXVyc0V0T3JnYW5lcykge1xuICAgICAgY29uc3QgZGF0YXNldE5hbWUgPSBwYXRoLmJhc2VuYW1lKGRhdGFzZXQuZmlsZW5hbWUsIFwiLmpzb25cIilcbiAgICAgIGlmIChvcHRpb25zLmRhdGFzZXQgJiYgZGF0YXNldE5hbWUgIT09IG9wdGlvbnMuZGF0YXNldCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgY2xvbmVHaXQoZ2l0R3JvdXBVcmwsIGRhdGFzZXROYW1lLCBkYXRhRGlyKVxuXG4gICAgICBjb25zdCBkYXRhc2V0UmF3RGlyOiBzdHJpbmcgPSBwYXRoLmpvaW4oZGF0YURpciwgZGF0YXNldE5hbWUpXG4gICAgICBjb25zdCBkYXRhc2V0Q2xlYW5EaXI6IHN0cmluZyA9IGAke2RhdGFzZXRSYXdEaXJ9X25ldHRveWVgXG4gICAgICBpZiAob3B0aW9ucy5wdWxsKSB7XG4gICAgICAgIGdpdC5yZXNldEFuZFB1bGwoZGF0YXNldENsZWFuRGlyKVxuICAgICAgfVxuXG4gICAgICBhbmFseXplQW5kUmVtb3ZlKGRhdGFzZXROYW1lLCBvcHRpb25zKVxuICAgICAgYXdhaXQgcHJvY2Vzc0ZpbGVzPEFjdGV1cj4oXG4gICAgICAgIGRhdGFzZXRSYXdEaXIsXG4gICAgICAgIGRhdGFzZXRDbGVhbkRpcixcbiAgICAgICAgW1wiYWN0ZXVyc1wiXSxcbiAgICAgICAgY2xlYW5BY3RldXIsXG4gICAgICAgIHtcbiAgICAgICAgICBmcm9tSnNvbjogQWN0ZXVyc0V0T3JnYW5lc0NvbnZlcnQudG9BY3RldXIsXG4gICAgICAgICAgdG9Kc29uOiBBY3RldXJzRXRPcmdhbmVzQ29udmVydC5hY3RldXJUb0pzb24sXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICApXG4gICAgICBhd2FpdCBwcm9jZXNzRmlsZXM8T3JnYW5lPihcbiAgICAgICAgZGF0YXNldFJhd0RpcixcbiAgICAgICAgZGF0YXNldENsZWFuRGlyLFxuICAgICAgICBbXCJvcmdhbmVzXCJdLFxuICAgICAgICBjbGVhbk9yZ2FuZSxcbiAgICAgICAge1xuICAgICAgICAgIGZyb21Kc29uOiBBY3RldXJzRXRPcmdhbmVzQ29udmVydC50b09yZ2FuZSxcbiAgICAgICAgICB0b0pzb246IEFjdGV1cnNFdE9yZ2FuZXNDb252ZXJ0Lm9yZ2FuZVRvSnNvbixcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgIClcblxuICAgICAgZXhpdENvZGUgPSBjb21taXRHaXQoZGF0YXNldENsZWFuRGlyLCBvcHRpb25zLCBleGl0Q29kZSwgW1xuICAgICAgICBcImFjdGV1cnNcIixcbiAgICAgICAgXCJvcmdhbmVzXCIsXG4gICAgICBdKVxuICAgIH1cbiAgfVxuXG4gIGlmIChlbmFibGVkRGF0YXNldHMgJiBFbmFibGVkRGF0YXNldHMuQWdlbmRhcykge1xuICAgIGZvciAoY29uc3QgZGF0YXNldCBvZiBjaG9zZW5EYXRhc2V0cy5hZ2VuZGFzKSB7XG4gICAgICBjb25zdCBkYXRhc2V0TmFtZSA9IHBhdGguYmFzZW5hbWUoZGF0YXNldC5maWxlbmFtZSwgXCIuanNvblwiKVxuICAgICAgaWYgKG9wdGlvbnMuZGF0YXNldCAmJiBkYXRhc2V0TmFtZSAhPT0gb3B0aW9ucy5kYXRhc2V0KSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGNsb25lR2l0KGdpdEdyb3VwVXJsLCBkYXRhc2V0TmFtZSwgZGF0YURpcilcbiAgICAgIGFuYWx5emVBbmRSZW1vdmUoZGF0YXNldE5hbWUsIG9wdGlvbnMpXG4gICAgICBjb25zdCBkYXRhc2V0UmF3RGlyOiBzdHJpbmcgPSBwYXRoLmpvaW4oZGF0YURpciwgZGF0YXNldE5hbWUpXG4gICAgICBjb25zdCBkYXRhc2V0Q2xlYW5EaXI6IHN0cmluZyA9IGAke2RhdGFzZXRSYXdEaXJ9X25ldHRveWVgXG5cbiAgICAgIGF3YWl0IHByb2Nlc3NGaWxlczxSZXVuaW9uPihcbiAgICAgICAgZGF0YXNldFJhd0RpcixcbiAgICAgICAgZGF0YXNldENsZWFuRGlyLFxuICAgICAgICBbXSxcbiAgICAgICAgY2xlYW5SZXVuaW9uLFxuICAgICAgICB7XG4gICAgICAgICAgZnJvbUpzb246IEFnZW5kYXNDb252ZXJ0LnRvUmV1bmlvbixcbiAgICAgICAgICB0b0pzb246IEFnZW5kYXNDb252ZXJ0LnJldW5pb25Ub0pzb24sXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICApXG5cbiAgICAgIGV4aXRDb2RlID0gY29tbWl0R2l0KGRhdGFzZXRDbGVhbkRpciwgb3B0aW9ucywgZXhpdENvZGUsIFtcIi5cIl0pXG4gICAgfVxuICB9XG5cbiAgaWYgKGVuYWJsZWREYXRhc2V0cyAmIEVuYWJsZWREYXRhc2V0cy5BbWVuZGVtZW50cykge1xuICAgIGZvciAoY29uc3QgZGF0YXNldCBvZiBjaG9zZW5EYXRhc2V0cy5hbWVuZGVtZW50cykge1xuICAgICAgY29uc3QgZGF0YXNldE5hbWUgPSBwYXRoLmJhc2VuYW1lKGRhdGFzZXQuZmlsZW5hbWUsIFwiLmpzb25cIilcbiAgICAgIGlmIChvcHRpb25zLmRhdGFzZXQgJiYgZGF0YXNldE5hbWUgIT09IG9wdGlvbnMuZGF0YXNldCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBjbG9uZUdpdChnaXRHcm91cFVybCwgZGF0YXNldE5hbWUsIGRhdGFEaXIpXG4gICAgICBhbmFseXplQW5kUmVtb3ZlKGRhdGFzZXROYW1lLCBvcHRpb25zKVxuICAgICAgY29uc3QgZGF0YXNldFJhd0Rpcjogc3RyaW5nID0gcGF0aC5qb2luKGRhdGFEaXIsIGRhdGFzZXROYW1lKVxuICAgICAgY29uc3QgZGF0YXNldENsZWFuRGlyOiBzdHJpbmcgPSBgJHtkYXRhc2V0UmF3RGlyfV9uZXR0b3llYFxuXG4gICAgICBhd2FpdCBwcm9jZXNzRmlsZXM8QW1lbmRlbWVudD4oXG4gICAgICAgIGRhdGFzZXRSYXdEaXIsXG4gICAgICAgIGRhdGFzZXRDbGVhbkRpcixcbiAgICAgICAgW10sXG4gICAgICAgIGNsZWFuQW1lbmRlbWVudCxcbiAgICAgICAge1xuICAgICAgICAgIGZyb21Kc29uOiBBbWVuZGVtZW50c0NvbnZlcnQudG9BbWVuZGVtZW50LFxuICAgICAgICAgIHRvSnNvbjogQW1lbmRlbWVudHNDb252ZXJ0LmFtZW5kZW1lbnRUb0pzb24sXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICApXG5cbiAgICAgIGV4aXRDb2RlID0gY29tbWl0R2l0KGRhdGFzZXRDbGVhbkRpciwgb3B0aW9ucywgZXhpdENvZGUsIFtcIi5cIl0pXG4gICAgfVxuICB9XG5cbiAgaWYgKGVuYWJsZWREYXRhc2V0cyAmIEVuYWJsZWREYXRhc2V0cy5Eb3NzaWVyc0xlZ2lzbGF0aWZzKSB7XG4gICAgZm9yIChjb25zdCBkYXRhc2V0IG9mIGNob3NlbkRhdGFzZXRzLmRvc3NpZXJzTGVnaXNsYXRpZnMpIHtcbiAgICAgIGNvbnN0IGRhdGFzZXROYW1lID0gcGF0aC5iYXNlbmFtZShkYXRhc2V0LmZpbGVuYW1lLCBcIi5qc29uXCIpXG4gICAgICBpZiAob3B0aW9ucy5kYXRhc2V0ICYmIGRhdGFzZXROYW1lICE9PSBvcHRpb25zLmRhdGFzZXQpIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgY2xvbmVHaXQoZ2l0R3JvdXBVcmwsIGRhdGFzZXROYW1lLCBkYXRhRGlyKVxuICAgICAgYW5hbHl6ZUFuZFJlbW92ZShkYXRhc2V0TmFtZSwgb3B0aW9ucylcbiAgICAgIGNvbnN0IGRhdGFzZXRSYXdEaXI6IHN0cmluZyA9IHBhdGguam9pbihkYXRhRGlyLCBkYXRhc2V0TmFtZSlcbiAgICAgIGNvbnN0IGRhdGFzZXRDbGVhbkRpcjogc3RyaW5nID0gYCR7ZGF0YXNldFJhd0Rpcn1fbmV0dG95ZWBcblxuICAgICAgYXdhaXQgcHJvY2Vzc0ZpbGVzPERvY3VtZW50PihcbiAgICAgICAgZGF0YXNldFJhd0RpcixcbiAgICAgICAgZGF0YXNldENsZWFuRGlyLFxuICAgICAgICBbXCJkb2N1bWVudHNcIl0sXG4gICAgICAgIGNsZWFuRG9jdW1lbnRPckRpdmlzaW9uLFxuICAgICAgICB7XG4gICAgICAgICAgZnJvbUpzb246IERvc3NpZXJzTGVnaXNsYXRpZnNDb252ZXJ0LnRvRG9jdW1lbnQsXG4gICAgICAgICAgdG9Kc29uOiBEb3NzaWVyc0xlZ2lzbGF0aWZzQ29udmVydC5kb2N1bWVudFRvSnNvbixcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgZG93bmxvYWRBbmRQYXJzZSxcbiAgICAgIClcbiAgICAgIGF3YWl0IHByb2Nlc3NGaWxlczxEb3NzaWVyUGFybGVtZW50YWlyZT4oXG4gICAgICAgIGRhdGFzZXRSYXdEaXIsXG4gICAgICAgIGRhdGFzZXRDbGVhbkRpcixcbiAgICAgICAgW1wiZG9zc2llcnNcIl0sXG4gICAgICAgIGNsZWFuRG9zc2llclBhcmxlbWVudGFpcmUsXG4gICAgICAgIHtcbiAgICAgICAgICBmcm9tSnNvbjogRG9zc2llcnNMZWdpc2xhdGlmc0NvbnZlcnQudG9Eb3NzaWVyUGFybGVtZW50YWlyZSxcbiAgICAgICAgICB0b0pzb246IERvc3NpZXJzTGVnaXNsYXRpZnNDb252ZXJ0LmRvc3NpZXJQYXJsZW1lbnRhaXJlVG9Kc29uLFxuICAgICAgICB9LFxuICAgICAgICBvcHRpb25zLFxuICAgICAgKVxuXG4gICAgICBleGl0Q29kZSA9IGNvbW1pdEdpdChkYXRhc2V0Q2xlYW5EaXIsIG9wdGlvbnMsIGV4aXRDb2RlLCBbXG4gICAgICAgIFwiZG9jdW1lbnRzXCIsXG4gICAgICAgIFwiZG9zc2llcnNcIixcbiAgICAgIF0pXG4gICAgfVxuICB9XG5cbiAgaWYgKGVuYWJsZWREYXRhc2V0cyAmIEVuYWJsZWREYXRhc2V0cy5TY3J1dGlucykge1xuICAgIGZvciAoY29uc3QgZGF0YXNldCBvZiBjaG9zZW5EYXRhc2V0cy5zY3J1dGlucykge1xuICAgICAgY29uc3QgZGF0YXNldE5hbWUgPSBwYXRoLmJhc2VuYW1lKGRhdGFzZXQuZmlsZW5hbWUsIFwiLmpzb25cIilcbiAgICAgIGlmIChvcHRpb25zLmRhdGFzZXQgJiYgZGF0YXNldE5hbWUgIT09IG9wdGlvbnMuZGF0YXNldCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBjbG9uZUdpdChnaXRHcm91cFVybCwgZGF0YXNldE5hbWUsIGRhdGFEaXIpXG4gICAgICBhbmFseXplQW5kUmVtb3ZlKGRhdGFzZXROYW1lLCBvcHRpb25zKVxuICAgICAgY29uc3QgZGF0YXNldFJhd0Rpcjogc3RyaW5nID0gcGF0aC5qb2luKGRhdGFEaXIsIGRhdGFzZXROYW1lKVxuICAgICAgY29uc3QgZGF0YXNldENsZWFuRGlyOiBzdHJpbmcgPSBgJHtkYXRhc2V0UmF3RGlyfV9uZXR0b3llYFxuXG4gICAgICBhd2FpdCBwcm9jZXNzRmlsZXM8U2NydXRpbj4oXG4gICAgICAgIGRhdGFzZXRSYXdEaXIsXG4gICAgICAgIGRhdGFzZXRDbGVhbkRpcixcbiAgICAgICAgW10sXG4gICAgICAgIGNsZWFuU2NydXRpbixcbiAgICAgICAge1xuICAgICAgICAgIGZyb21Kc29uOiBTY3J1dGluc0NvbnZlcnQudG9TY3J1dGluLFxuICAgICAgICAgIHRvSnNvbjogU2NydXRpbnNDb252ZXJ0LnNjcnV0aW5Ub0pzb24sXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICApXG5cbiAgICAgIGV4aXRDb2RlID0gY29tbWl0R2l0KGRhdGFzZXRDbGVhbkRpciwgb3B0aW9ucywgZXhpdENvZGUsIFtcIi5cIl0pXG4gICAgfVxuICB9XG5cbiAgaWYgKGVuYWJsZWREYXRhc2V0cyAmIEVuYWJsZWREYXRhc2V0cy5RdWVzdGlvbnMpIHtcbiAgICBmb3IgKGNvbnN0IGRhdGFzZXQgb2YgZGF0YXNldHMucXVlc3Rpb25zKSB7XG4gICAgICBjb25zdCBkYXRhc2V0TmFtZSA9IHBhdGguYmFzZW5hbWUoZGF0YXNldC5maWxlbmFtZSwgXCIuanNvblwiKVxuICAgICAgaWYgKG9wdGlvbnMuZGF0YXNldCAmJiBkYXRhc2V0TmFtZSAhPT0gb3B0aW9ucy5kYXRhc2V0KSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGNsb25lR2l0KGdpdEdyb3VwVXJsLCBkYXRhc2V0TmFtZSwgZGF0YURpcilcbiAgICAgIGFuYWx5emVBbmRSZW1vdmUoZGF0YXNldE5hbWUsIG9wdGlvbnMpXG4gICAgICBjb25zdCBkYXRhc2V0UmF3RGlyOiBzdHJpbmcgPSBwYXRoLmpvaW4oZGF0YURpciwgZGF0YXNldE5hbWUpXG4gICAgICBjb25zdCBkYXRhc2V0Q2xlYW5EaXI6IHN0cmluZyA9IGAke2RhdGFzZXRSYXdEaXJ9X25ldHRveWVgXG5cbiAgICAgIGF3YWl0IHByb2Nlc3NGaWxlczxRdWVzdGlvbj4oXG4gICAgICAgIGRhdGFzZXRSYXdEaXIsXG4gICAgICAgIGRhdGFzZXRDbGVhbkRpcixcbiAgICAgICAgW10sXG4gICAgICAgIGNsZWFuUXVlc3Rpb24sXG4gICAgICAgIHtcbiAgICAgICAgICBmcm9tSnNvbjogUXVlc3Rpb25zQ29udmVydC50b1F1ZXN0aW9uLFxuICAgICAgICAgIHRvSnNvbjogUXVlc3Rpb25zQ29udmVydC5xdWVzdGlvblRvSnNvbixcbiAgICAgICAgfSxcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgIClcblxuICAgICAgZXhpdENvZGUgPSBjb21taXRHaXQoZGF0YXNldENsZWFuRGlyLCBvcHRpb25zLCBleGl0Q29kZSwgW1wiLlwiXSlcbiAgICB9XG4gIH1cblxuICBpZiAoZW5hYmxlZERhdGFzZXRzICYgRW5hYmxlZERhdGFzZXRzLkNvbXB0ZXNSZW5kdXNTZWFuY2VzKSB7XG4gICAgZm9yIChjb25zdCBkYXRhc2V0IG9mIGRhdGFzZXRzLmNvbXB0ZXNSZW5kdXNTZWFuY2VzKSB7XG4gICAgICBjb25zdCBkYXRhc2V0TmFtZSA9IHBhdGguYmFzZW5hbWUoZGF0YXNldC5maWxlbmFtZSwgXCIueG1sXCIpXG4gICAgICBpZiAob3B0aW9ucy5kYXRhc2V0ICYmIGRhdGFzZXROYW1lICE9PSBvcHRpb25zLmRhdGFzZXQpIHtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgY2xvbmVHaXQoZ2l0R3JvdXBVcmwsIGRhdGFzZXROYW1lLCBkYXRhRGlyKVxuICAgICAgYW5hbHl6ZUFuZFJlbW92ZShkYXRhc2V0TmFtZSwgb3B0aW9ucylcbiAgICAgIGNvbnN0IGRhdGFzZXRSYXdEaXI6IHN0cmluZyA9IHBhdGguam9pbihkYXRhRGlyLCBkYXRhc2V0TmFtZSlcbiAgICAgIGNvbnN0IGRhdGFzZXRDbGVhbkRpcjogc3RyaW5nID0gYCR7ZGF0YXNldFJhd0Rpcn1fbmV0dG95ZWBcblxuICAgICAgYXdhaXQgcHJvY2Vzc0ZpbGVzPENvbXB0ZVJlbmR1PihcbiAgICAgICAgZGF0YXNldFJhd0RpcixcbiAgICAgICAgZGF0YXNldENsZWFuRGlyLFxuICAgICAgICBbXSxcbiAgICAgICAgY2xlYW5Db21wdGVSZW5kdSxcbiAgICAgICAge1xuICAgICAgICAgIGZyb21Kc29uOiBDb21wdGVzUmVuZHVzQ29udmVydC50b0NvbXB0ZVJlbmR1LFxuICAgICAgICAgIHRvSnNvbjogQ29tcHRlc1JlbmR1c0NvbnZlcnQuY29tcHRlUmVuZHVUb0pzb24sXG4gICAgICAgIH0sXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICApXG5cbiAgICAgIGV4aXRDb2RlID0gY29tbWl0R2l0KGRhdGFzZXRDbGVhbkRpciwgb3B0aW9ucywgZXhpdENvZGUsIFtcIi5cIl0pXG4gICAgfVxuICB9XG5cbiAgLy8gUmVzdG9yZSBzdGFuZGFyZCBjb252ZXJzaW9uIG9mIGRhdGVzIHRvIEpTT04uXG4gIERhdGUucHJvdG90eXBlLnRvSlNPTiA9IGV4aXN0aW5nRGF0ZVRvSnNvblxuXG4gIGlmICghb3B0aW9ucy5zaWxlbnQpIHtcbiAgICBjb25zb2xlLmxvZyhcIkZpbmlzaGVkICFcIilcbiAgfVxuXG4gIHJldHVybiBleGl0Q29kZVxufVxuXG5mdW5jdGlvbiBhbmFseXplQW5kUmVtb3ZlKGRhdGFzZXROYW1lOiBzdHJpbmcsIG9wdGlvbnM6IGFueSk6IGFueSB7XG4gIGNvbnN0IGRhdGFEaXIgPSBvcHRpb25zLmRhdGFEaXJcbiAgY29uc3QgZGF0YXNldFJhd0Rpcjogc3RyaW5nID0gcGF0aC5qb2luKGRhdGFEaXIsIGRhdGFzZXROYW1lKVxuICBjb25zdCBkYXRhc2V0Q2xlYW5EaXI6IHN0cmluZyA9IGAke2RhdGFzZXRSYXdEaXJ9X25ldHRveWVgXG4gIGlmICghb3B0aW9ucy5zaWxlbnQpIHtcbiAgICBjb25zb2xlLmxvZyhgQ2xlYW5pbmcgZGlyZWN0b3J5OiAke2RhdGFzZXRDbGVhbkRpcn3igKZgKVxuICB9XG4gIGZzLmVuc3VyZURpclN5bmMoZGF0YXNldENsZWFuRGlyKVxuICBmb3IgKGNvbnN0IGZpbGVuYW1lIG9mIGZzLnJlYWRkaXJTeW5jKGRhdGFzZXRDbGVhbkRpcikpIHtcbiAgICBpZiAoZmlsZW5hbWVbMF0gPT09IFwiLlwiKSB7XG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICBjb25zdCBwYXRobmFtZSA9IHBhdGguam9pbihkYXRhc2V0Q2xlYW5EaXIsIGZpbGVuYW1lKVxuICAgIGZzLnJlbW92ZVN5bmMocGF0aG5hbWUpXG4gIH1cbn1cblxuZnVuY3Rpb24gY29tbWl0QW5kUHVzaFVpZChcbiAgcmVwb3NpdG9yeURpcjogc3RyaW5nLFxuICBvcHRpb25zOiBhbnksXG4gIHN1YmRpcmVjdG9yaWVzOiBhbnksXG4pOiBib29sZWFuIHtcbiAgbGV0IGVycm9yID0gZmFsc2VcbiAgaWYgKG9wdGlvbnMuY29tbWl0KSB7XG4gICAgZ2l0LnVpZEJyYW5jaFVwZGF0ZShcbiAgICAgIHJlcG9zaXRvcnlEaXIsXG4gICAgICBzdWJkaXJlY3RvcmllcyxcbiAgICAgIG9wdGlvbnNbXCJuby1yZXNldC1hZnRlci1jb21taXRcIl0sXG4gICAgKVxuICAgIGZvciAoY29uc3QgcmVtb3RlIG9mIG9wdGlvbnMucmVtb3RlIHx8IFtdKSB7XG4gICAgICB0cnkge1xuICAgICAgICBnaXQucnVuKHJlcG9zaXRvcnlEaXIsIGBwdXNoIC0tcXVpZXQgJHtyZW1vdGV9IHVpZDp1aWRgKVxuICAgICAgfSBjYXRjaCAoY2hpbGRQcm9jZXNzKSB7XG4gICAgICAgIGVycm9yID0gdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gZXJyb3Jcbn1cblxuZnVuY3Rpb24gbWFpbihhcmd2OiBhbnkpOiBQcm9taXNlPG51bWJlcj4ge1xuICBjb25zdCBvcHRpb25zID0gcGFyc2VBcmdzKGFyZ3YpXG4gIHJldHVybiBjbGVhblJlb3JnYW5pemVkRGF0YShvcHRpb25zKVxufVxuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbmlmIChwcm9jZXNzLmFyZ3ZbMV0uZW5kc1dpdGgoXCJjbGVhbl9yZW9yZ2FuaXplZF9kYXRhLnRzXCIpKSB7XG4gIG1haW4ocHJvY2Vzcy5hcmd2KS50aGVuKHByb2Nlc3MuZXhpdClcbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsT0FBT0EsZUFBZSxNQUFNLG1CQUFtQjtBQUMvQyxPQUFPQyxFQUFFLE1BQU0sVUFBVTtBQUN6QixPQUFPQyxJQUFJLE1BQU0sTUFBTTtBQUFBLFNBRXJCQyxXQUFXLEVBQ1hDLGVBQWUsRUFDZkMsdUJBQXVCLEVBQ3ZCQyx5QkFBeUIsRUFDekJDLFdBQVcsRUFDWEMsWUFBWSxFQUNaQyxZQUFZLEVBQ1pDLGFBQWEsRUFDYkMsZ0JBQWdCO0FBQUEsU0FHaEJDLFFBQVEsRUFDUkMsZUFBZSxFQUNmQyxrQkFBa0IsRUFDbEJDLG1CQUFtQjtBQUFBLFNBRVpDLGdCQUFnQjtBQUFBLFNBQ2hCQyxrQkFBa0IsRUFBRUMsaUJBQWlCO0FBQUEsU0FDckNDLE9BQU87QUFBQSxPQUNULEtBQUtDLEdBQUc7QUFBQSxTQUdiQyxPQUFPLElBQUlDLHVCQUF1QjtBQUFBLFNBRzNCRCxPQUFPLElBQUlFLGNBQWM7QUFBQSxTQUNiRixPQUFPLElBQUlHLGtCQUFrQjtBQUFBLFNBRWhESCxPQUFPLElBQUlJLDBCQUEwQjtBQUFBLFNBSTlCSixPQUFPLElBQUlLLGVBQWU7QUFBQSxTQUMxQkwsT0FBTyxJQUFJTSxnQkFBZ0I7QUFBQSxTQUMzQk4sT0FBTyxJQUFJTyxvQkFBb0I7QUFBQSxTQUV0Q0MsV0FBVyxFQUNYQyxZQUFZLEVBQ1pDLFlBQVksRUFDWkMsaUJBQWlCLEVBQ2pCQyxnQkFBZ0IsRUFDaEJDLG9CQUFvQixFQUNwQkMsWUFBWSxFQUNaQyxhQUFh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