UNPKG

@tricoteuses/assemblee

Version:

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

158 lines (155 loc) 27.1 kB
import { execSync } from "child_process"; import commandLineArgs from "command-line-args"; import fs from "fs-extra"; import path from "path"; import stream from "stream"; import util from "util"; import * as git from "../git.mjs"; import { iterLoadAssembleeActeurs } from "../loaders.mjs"; import { CodeTypeOrgane, TypeMandat } from "../types/acteurs_et_organes.mjs"; import { cloneOption, commitOption, remoteOption, silentOption, dataDirDefaultOption, pullOption, legislatureOption, fetchOption } from "./shared/cli_helpers.mjs"; const optionsDefinitions = [cloneOption, commitOption, remoteOption, silentOption, dataDirDefaultOption, pullOption, fetchOption, legislatureOption, { alias: "S", defaultValue: false, name: "square", type: Boolean }, { alias: "w", defaultValue: 150, name: "width", type: Number }, { alias: "h", defaultValue: 192, name: "height", type: Number }]; const options = commandLineArgs(optionsDefinitions); export function cloneAndUpdateGitRepository(photosDirName, options) { const gitGroupUrl = options.clone ? options.clone.trim().replace(/\/+$/, "") : undefined; const photosDir = path.join(options.dataDir, photosDirName); git.clone(gitGroupUrl, photosDirName, options.dataDir); if (options.pull) { git.resetAndPull(photosDir); } } export function resizePhoto(acteur, width, height, photosDir, photoFilename, options) { const ident = acteur.etatCivil.ident; if (!options.silent) { console.log(`Resizing photo ${photoFilename} for ${ident.prenom} ${ident.nom}…`); } execSync(`gm convert -resize ${width}x${height}! ${photoFilename}.jpg ${photoFilename}_${width}x${height}.jpg`, { cwd: photosDir }); } export async function downloadPhoto(urlPhoto, photoTempFilePath, photoFilePath, missingPhotoFilePath, retries = 3) { const pipeline = util.promisify(stream.pipeline); for (let attempt = 1; attempt <= retries; attempt++) { try { const response = await fetch(urlPhoto); if (response.ok) { await pipeline(response.body, fs.createWriteStream(photoTempFilePath)); fs.renameSync(photoTempFilePath, photoFilePath); return; } console.warn(`Fetch failed: ${urlPhoto} (Attempt ${attempt}) - Status: ${response.status} ${response.statusText}`); } catch (error) { console.log(error); console.warn(`Attempt ${attempt} failed for ${urlPhoto}`, error); } } if (fs.existsSync(photoFilePath)) { console.warn(`Reusing existing image: ${photoFilePath}`); } else { console.warn(`Using blank image: ${missingPhotoFilePath}`); fs.copyFileSync(missingPhotoFilePath, photoFilePath); } } export function createMosaic(acteurUids, photosDir, photosWidth, photosHeight, mosaicFilename) { const photoByIdActeur = {}; const rowsFilenames = []; if (acteurUids.length === 0) return; for (let acteurIndex = 0, rowIndex = 0; acteurIndex < acteurUids.length; acteurIndex += 25, rowIndex++) { const row = acteurUids.slice(acteurIndex, acteurIndex + 25); const photosFilenames = row.map((acteurUid, columnIndex) => { const photoFilename = `${acteurUid}_${photosWidth}x${photosHeight}.jpg`; photoByIdActeur[acteurUid] = { chemin: `${photosDir}/${photoFilename}`, cheminMosaique: `${photosDir}/${mosaicFilename}.jpg`, largeur: photosWidth, hauteur: photosHeight, xMosaique: columnIndex * photosWidth, yMosaique: rowIndex * photosHeight }; return photoFilename; }); const rowFilename = `row-${rowIndex}.jpg`; execSync(`gm convert ${photosFilenames.join(" ")} +append ${rowFilename}`, { cwd: photosDir }); rowsFilenames.push(rowFilename); } // Combine all rows into one image execSync(`gm convert ${rowsFilenames.join(" ")} -append ${mosaicFilename}.jpg`, { cwd: photosDir }); // Cleanup individual row images rowsFilenames.forEach(rowFilename => { fs.unlinkSync(path.join(photosDir, rowFilename)); }); const jsonFilePath = path.join(photosDir, `${mosaicFilename}.json`); fs.writeFileSync(jsonFilePath, JSON.stringify(photoByIdActeur, null, 2)); } async function retrievePhotosDeputes() { const dataDir = options.dataDir; const photosPrefix = "photos_deputes"; const photosDirName = `${photosPrefix}_${options.legislature}`; const photosDir = path.join(dataDir, photosDirName); const photosWidth = options.width; const photosHeight = options.height; const missingPhotoFilePath = `images/transparent_${photosWidth}x${photosHeight}.jpg`; cloneAndUpdateGitRepository(photosDirName, options); fs.ensureDirSync(photosDir); const acteurUids = []; for (const { acteur } of iterLoadAssembleeActeurs(dataDir, options.legislature, { noValidation: true })) { const { mandats } = acteur; if (!mandats) continue; const mandatDepute = mandats.find(mandat => mandat.xsiType === TypeMandat.MandatParlementaireType && mandat.legislature === options.legislature?.toString() && mandat.typeOrgane === CodeTypeOrgane.Assemblee); if (!mandatDepute) continue; const numeroDepute = acteur.uid.substring(2); // Download photos. if (options.fetch) { const ident = acteur.etatCivil.ident; const photoFilename = `${numeroDepute}.jpg`; const photoFilePath = path.join(photosDir, photoFilename); const photoTempFilename = `${numeroDepute}_temp.jpg`; const photoTempFilePath = path.join(photosDir, photoTempFilename); let urlPhoto = `http://www2.assemblee-nationale.fr/static/tribun/${options.legislature}/photos/${photoFilename}`; if (options.square) { urlPhoto = `https://www2.assemblee-nationale.fr/static/tribun/${options.legislature}/photos/carre/${photoFilename}`; } if (!options.silent) { console.log(`Loading photo ${urlPhoto} for ${ident.prenom} ${ident.nom}…`); } await downloadPhoto(urlPhoto, photoTempFilePath, photoFilePath, missingPhotoFilePath); resizePhoto(acteur, photosWidth, photosHeight, photosDir, numeroDepute, options); } acteurUids.push(numeroDepute); } createMosaic(acteurUids, photosDir, photosWidth, photosHeight, "deputes"); if (options.commit) { return git.commitAndPush(photosDir, "Nouvelle moisson", options.remote); } return 0; } retrievePhotosDeputes().then(exitCode => process.exit(exitCode)).catch(error => { console.log(error); process.exit(1); }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJleGVjU3luYyIsImNvbW1hbmRMaW5lQXJncyIsImZzIiwicGF0aCIsInN0cmVhbSIsInV0aWwiLCJnaXQiLCJpdGVyTG9hZEFzc2VtYmxlZUFjdGV1cnMiLCJDb2RlVHlwZU9yZ2FuZSIsIlR5cGVNYW5kYXQiLCJjbG9uZU9wdGlvbiIsImNvbW1pdE9wdGlvbiIsInJlbW90ZU9wdGlvbiIsInNpbGVudE9wdGlvbiIsImRhdGFEaXJEZWZhdWx0T3B0aW9uIiwicHVsbE9wdGlvbiIsImxlZ2lzbGF0dXJlT3B0aW9uIiwiZmV0Y2hPcHRpb24iLCJvcHRpb25zRGVmaW5pdGlvbnMiLCJhbGlhcyIsImRlZmF1bHRWYWx1ZSIsIm5hbWUiLCJ0eXBlIiwiQm9vbGVhbiIsIk51bWJlciIsIm9wdGlvbnMiLCJjbG9uZUFuZFVwZGF0ZUdpdFJlcG9zaXRvcnkiLCJwaG90b3NEaXJOYW1lIiwiZ2l0R3JvdXBVcmwiLCJjbG9uZSIsInRyaW0iLCJyZXBsYWNlIiwidW5kZWZpbmVkIiwicGhvdG9zRGlyIiwiam9pbiIsImRhdGFEaXIiLCJwdWxsIiwicmVzZXRBbmRQdWxsIiwicmVzaXplUGhvdG8iLCJhY3RldXIiLCJ3aWR0aCIsImhlaWdodCIsInBob3RvRmlsZW5hbWUiLCJpZGVudCIsImV0YXRDaXZpbCIsInNpbGVudCIsImNvbnNvbGUiLCJsb2ciLCJwcmVub20iLCJub20iLCJjd2QiLCJkb3dubG9hZFBob3RvIiwidXJsUGhvdG8iLCJwaG90b1RlbXBGaWxlUGF0aCIsInBob3RvRmlsZVBhdGgiLCJtaXNzaW5nUGhvdG9GaWxlUGF0aCIsInJldHJpZXMiLCJwaXBlbGluZSIsInByb21pc2lmeSIsImF0dGVtcHQiLCJyZXNwb25zZSIsImZldGNoIiwib2siLCJib2R5IiwiY3JlYXRlV3JpdGVTdHJlYW0iLCJyZW5hbWVTeW5jIiwid2FybiIsInN0YXR1cyIsInN0YXR1c1RleHQiLCJlcnJvciIsImV4aXN0c1N5bmMiLCJjb3B5RmlsZVN5bmMiLCJjcmVhdGVNb3NhaWMiLCJhY3RldXJVaWRzIiwicGhvdG9zV2lkdGgiLCJwaG90b3NIZWlnaHQiLCJtb3NhaWNGaWxlbmFtZSIsInBob3RvQnlJZEFjdGV1ciIsInJvd3NGaWxlbmFtZXMiLCJsZW5ndGgiLCJhY3RldXJJbmRleCIsInJvd0luZGV4Iiwicm93Iiwic2xpY2UiLCJwaG90b3NGaWxlbmFtZXMiLCJtYXAiLCJhY3RldXJVaWQiLCJjb2x1bW5JbmRleCIsImNoZW1pbiIsImNoZW1pbk1vc2FpcXVlIiwibGFyZ2V1ciIsImhhdXRldXIiLCJ4TW9zYWlxdWUiLCJ5TW9zYWlxdWUiLCJyb3dGaWxlbmFtZSIsInB1c2giLCJmb3JFYWNoIiwidW5saW5rU3luYyIsImpzb25GaWxlUGF0aCIsIndyaXRlRmlsZVN5bmMiLCJKU09OIiwic3RyaW5naWZ5IiwicmV0cmlldmVQaG90b3NEZXB1dGVzIiwicGhvdG9zUHJlZml4IiwibGVnaXNsYXR1cmUiLCJlbnN1cmVEaXJTeW5jIiwibm9WYWxpZGF0aW9uIiwibWFuZGF0cyIsIm1hbmRhdERlcHV0ZSIsImZpbmQiLCJtYW5kYXQiLCJ4c2lUeXBlIiwiTWFuZGF0UGFybGVtZW50YWlyZVR5cGUiLCJ0b1N0cmluZyIsInR5cGVPcmdhbmUiLCJBc3NlbWJsZWUiLCJudW1lcm9EZXB1dGUiLCJ1aWQiLCJzdWJzdHJpbmciLCJwaG90b1RlbXBGaWxlbmFtZSIsInNxdWFyZSIsImNvbW1pdCIsImNvbW1pdEFuZFB1c2giLCJyZW1vdGUiLCJ0aGVuIiwiZXhpdENvZGUiLCJwcm9jZXNzIiwiZXhpdCIsImNhdGNoIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NjcmlwdHMvcmV0cmlldmVfZGVwdXRlc19waG90b3MudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXhlY1N5bmMgfSBmcm9tIFwiY2hpbGRfcHJvY2Vzc1wiXG5pbXBvcnQgY29tbWFuZExpbmVBcmdzIGZyb20gXCJjb21tYW5kLWxpbmUtYXJnc1wiXG5pbXBvcnQgZnMgZnJvbSBcImZzLWV4dHJhXCJcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCJcbmltcG9ydCBzdHJlYW0gZnJvbSBcInN0cmVhbVwiXG5pbXBvcnQgdXRpbCBmcm9tIFwidXRpbFwiXG5pbXBvcnQgKiBhcyBnaXQgZnJvbSBcIi4uL2dpdFwiXG5cbmltcG9ydCB7IGl0ZXJMb2FkQXNzZW1ibGVlQWN0ZXVycyB9IGZyb20gXCIuLi9sb2FkZXJzXCJcbmltcG9ydCB7XG4gIEFjdGV1cixcbiAgQ29kZVR5cGVPcmdhbmUsXG4gIE1hbmRhdCxcbiAgUGhvdG8sXG4gIFR5cGVNYW5kYXQsXG59IGZyb20gXCIuLi90eXBlcy9hY3RldXJzX2V0X29yZ2FuZXNcIlxuaW1wb3J0IHtcbiAgY2xvbmVPcHRpb24sXG4gIGNvbW1pdE9wdGlvbixcbiAgcmVtb3RlT3B0aW9uLFxuICBzaWxlbnRPcHRpb24sXG4gIGRhdGFEaXJEZWZhdWx0T3B0aW9uLFxuICBwdWxsT3B0aW9uLFxuICBsZWdpc2xhdHVyZU9wdGlvbixcbiAgZmV0Y2hPcHRpb24sXG59IGZyb20gXCIuL3NoYXJlZC9jbGlfaGVscGVyc1wiXG5cbmNvbnN0IG9wdGlvbnNEZWZpbml0aW9ucyA9IFtcbiAgY2xvbmVPcHRpb24sXG4gIGNvbW1pdE9wdGlvbixcbiAgcmVtb3RlT3B0aW9uLFxuICBzaWxlbnRPcHRpb24sXG4gIGRhdGFEaXJEZWZhdWx0T3B0aW9uLFxuICBwdWxsT3B0aW9uLFxuICBmZXRjaE9wdGlvbixcbiAgbGVnaXNsYXR1cmVPcHRpb24sXG4gIHtcbiAgICBhbGlhczogXCJTXCIsXG4gICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICBuYW1lOiBcInNxdWFyZVwiLFxuICAgIHR5cGU6IEJvb2xlYW4sXG4gIH0sXG4gIHtcbiAgICBhbGlhczogXCJ3XCIsXG4gICAgZGVmYXVsdFZhbHVlOiAxNTAsXG4gICAgbmFtZTogXCJ3aWR0aFwiLFxuICAgIHR5cGU6IE51bWJlcixcbiAgfSxcbiAge1xuICAgIGFsaWFzOiBcImhcIixcbiAgICBkZWZhdWx0VmFsdWU6IDE5MixcbiAgICBuYW1lOiBcImhlaWdodFwiLFxuICAgIHR5cGU6IE51bWJlcixcbiAgfSxcbl1cbmNvbnN0IG9wdGlvbnMgPSBjb21tYW5kTGluZUFyZ3Mob3B0aW9uc0RlZmluaXRpb25zKVxuXG5leHBvcnQgZnVuY3Rpb24gY2xvbmVBbmRVcGRhdGVHaXRSZXBvc2l0b3J5KFxuICBwaG90b3NEaXJOYW1lOiBzdHJpbmcsXG4gIG9wdGlvbnM6IGFueSxcbik6IHZvaWQge1xuICBjb25zdCBnaXRHcm91cFVybCA9IG9wdGlvbnMuY2xvbmVcbiAgICA/IG9wdGlvbnMuY2xvbmUudHJpbSgpLnJlcGxhY2UoL1xcLyskLywgXCJcIilcbiAgICA6IHVuZGVmaW5lZFxuICBjb25zdCBwaG90b3NEaXIgPSBwYXRoLmpvaW4ob3B0aW9ucy5kYXRhRGlyLCBwaG90b3NEaXJOYW1lKVxuICBnaXQuY2xvbmUoZ2l0R3JvdXBVcmwsIHBob3Rvc0Rpck5hbWUsIG9wdGlvbnMuZGF0YURpcilcblxuICBpZiAob3B0aW9ucy5wdWxsKSB7XG4gICAgZ2l0LnJlc2V0QW5kUHVsbChwaG90b3NEaXIpXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlc2l6ZVBob3RvKFxuICBhY3RldXI6IEFjdGV1cixcbiAgd2lkdGg6IG51bWJlcixcbiAgaGVpZ2h0OiBudW1iZXIsXG4gIHBob3Rvc0Rpcjogc3RyaW5nLFxuICBwaG90b0ZpbGVuYW1lOiBzdHJpbmcsXG4gIG9wdGlvbnM6IGFueSxcbik6IHZvaWQge1xuICBjb25zdCBpZGVudCA9IGFjdGV1ci5ldGF0Q2l2aWwuaWRlbnRcbiAgaWYgKCFvcHRpb25zLnNpbGVudCkge1xuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYFJlc2l6aW5nIHBob3RvICR7cGhvdG9GaWxlbmFtZX0gZm9yICR7aWRlbnQucHJlbm9tfSAke2lkZW50Lm5vbX3igKZgLFxuICAgIClcbiAgfVxuICBleGVjU3luYyhcbiAgICBgZ20gY29udmVydCAtcmVzaXplICR7d2lkdGh9eCR7aGVpZ2h0fSEgJHtwaG90b0ZpbGVuYW1lfS5qcGcgJHtwaG90b0ZpbGVuYW1lfV8ke3dpZHRofXgke2hlaWdodH0uanBnYCxcbiAgICB7XG4gICAgICBjd2Q6IHBob3Rvc0RpcixcbiAgICB9LFxuICApXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb3dubG9hZFBob3RvKFxuICB1cmxQaG90bzogc3RyaW5nLFxuICBwaG90b1RlbXBGaWxlUGF0aDogc3RyaW5nLFxuICBwaG90b0ZpbGVQYXRoOiBzdHJpbmcsXG4gIG1pc3NpbmdQaG90b0ZpbGVQYXRoOiBzdHJpbmcsXG4gIHJldHJpZXM6IG51bWJlciA9IDMsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcGlwZWxpbmUgPSB1dGlsLnByb21pc2lmeShzdHJlYW0ucGlwZWxpbmUpXG5cbiAgZm9yIChsZXQgYXR0ZW1wdCA9IDE7IGF0dGVtcHQgPD0gcmV0cmllczsgYXR0ZW1wdCsrKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsUGhvdG8pXG5cbiAgICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgICBhd2FpdCBwaXBlbGluZShcbiAgICAgICAgICByZXNwb25zZS5ib2R5IGFzIHVua25vd24gYXMgTm9kZUpTLlJlYWRhYmxlU3RyZWFtLFxuICAgICAgICAgIGZzLmNyZWF0ZVdyaXRlU3RyZWFtKHBob3RvVGVtcEZpbGVQYXRoKSxcbiAgICAgICAgKVxuICAgICAgICBmcy5yZW5hbWVTeW5jKHBob3RvVGVtcEZpbGVQYXRoLCBwaG90b0ZpbGVQYXRoKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgRmV0Y2ggZmFpbGVkOiAke3VybFBob3RvfSAoQXR0ZW1wdCAke2F0dGVtcHR9KSAtIFN0YXR1czogJHtyZXNwb25zZS5zdGF0dXN9ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gLFxuICAgICAgKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmxvZyhlcnJvcilcbiAgICAgIGNvbnNvbGUud2FybihgQXR0ZW1wdCAke2F0dGVtcHR9IGZhaWxlZCBmb3IgJHt1cmxQaG90b31gLCBlcnJvcilcbiAgICB9XG4gIH1cblxuICBpZiAoZnMuZXhpc3RzU3luYyhwaG90b0ZpbGVQYXRoKSkge1xuICAgIGNvbnNvbGUud2FybihgUmV1c2luZyBleGlzdGluZyBpbWFnZTogJHtwaG90b0ZpbGVQYXRofWApXG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS53YXJuKGBVc2luZyBibGFuayBpbWFnZTogJHttaXNzaW5nUGhvdG9GaWxlUGF0aH1gKVxuICAgIGZzLmNvcHlGaWxlU3luYyhtaXNzaW5nUGhvdG9GaWxlUGF0aCwgcGhvdG9GaWxlUGF0aClcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTW9zYWljKFxuICBhY3RldXJVaWRzOiBzdHJpbmdbXSxcbiAgcGhvdG9zRGlyOiBzdHJpbmcsXG4gIHBob3Rvc1dpZHRoOiBudW1iZXIsXG4gIHBob3Rvc0hlaWdodDogbnVtYmVyLFxuICBtb3NhaWNGaWxlbmFtZTogc3RyaW5nLFxuKTogdm9pZCB7XG4gIGNvbnN0IHBob3RvQnlJZEFjdGV1cjogeyBbdWlkOiBzdHJpbmddOiBQaG90byB9ID0ge31cbiAgY29uc3Qgcm93c0ZpbGVuYW1lczogc3RyaW5nW10gPSBbXVxuXG4gIGlmIChhY3RldXJVaWRzLmxlbmd0aCA9PT0gMCkgcmV0dXJuXG5cbiAgZm9yIChcbiAgICBsZXQgYWN0ZXVySW5kZXggPSAwLCByb3dJbmRleCA9IDA7XG4gICAgYWN0ZXVySW5kZXggPCBhY3RldXJVaWRzLmxlbmd0aDtcbiAgICBhY3RldXJJbmRleCArPSAyNSwgcm93SW5kZXgrK1xuICApIHtcbiAgICBjb25zdCByb3cgPSBhY3RldXJVaWRzLnNsaWNlKGFjdGV1ckluZGV4LCBhY3RldXJJbmRleCArIDI1KVxuICAgIGNvbnN0IHBob3Rvc0ZpbGVuYW1lczogc3RyaW5nW10gPSByb3cubWFwKChhY3RldXJVaWQsIGNvbHVtbkluZGV4KSA9PiB7XG4gICAgICBjb25zdCBwaG90b0ZpbGVuYW1lID0gYCR7YWN0ZXVyVWlkfV8ke3Bob3Rvc1dpZHRofXgke3Bob3Rvc0hlaWdodH0uanBnYFxuICAgICAgcGhvdG9CeUlkQWN0ZXVyW2FjdGV1clVpZF0gPSB7XG4gICAgICAgIGNoZW1pbjogYCR7cGhvdG9zRGlyfS8ke3Bob3RvRmlsZW5hbWV9YCxcbiAgICAgICAgY2hlbWluTW9zYWlxdWU6IGAke3Bob3Rvc0Rpcn0vJHttb3NhaWNGaWxlbmFtZX0uanBnYCxcbiAgICAgICAgbGFyZ2V1cjogcGhvdG9zV2lkdGgsXG4gICAgICAgIGhhdXRldXI6IHBob3Rvc0hlaWdodCxcbiAgICAgICAgeE1vc2FpcXVlOiBjb2x1bW5JbmRleCAqIHBob3Rvc1dpZHRoLFxuICAgICAgICB5TW9zYWlxdWU6IHJvd0luZGV4ICogcGhvdG9zSGVpZ2h0LFxuICAgICAgfVxuICAgICAgcmV0dXJuIHBob3RvRmlsZW5hbWVcbiAgICB9KVxuXG4gICAgY29uc3Qgcm93RmlsZW5hbWUgPSBgcm93LSR7cm93SW5kZXh9LmpwZ2BcbiAgICBleGVjU3luYyhgZ20gY29udmVydCAke3Bob3Rvc0ZpbGVuYW1lcy5qb2luKFwiIFwiKX0gK2FwcGVuZCAke3Jvd0ZpbGVuYW1lfWAsIHtcbiAgICAgIGN3ZDogcGhvdG9zRGlyLFxuICAgIH0pXG4gICAgcm93c0ZpbGVuYW1lcy5wdXNoKHJvd0ZpbGVuYW1lKVxuICB9XG5cbiAgLy8gQ29tYmluZSBhbGwgcm93cyBpbnRvIG9uZSBpbWFnZVxuICBleGVjU3luYyhcbiAgICBgZ20gY29udmVydCAke3Jvd3NGaWxlbmFtZXMuam9pbihcIiBcIil9IC1hcHBlbmQgJHttb3NhaWNGaWxlbmFtZX0uanBnYCxcbiAgICB7IGN3ZDogcGhvdG9zRGlyIH0sXG4gIClcblxuICAvLyBDbGVhbnVwIGluZGl2aWR1YWwgcm93IGltYWdlc1xuICByb3dzRmlsZW5hbWVzLmZvckVhY2goKHJvd0ZpbGVuYW1lKSA9PiB7XG4gICAgZnMudW5saW5rU3luYyhwYXRoLmpvaW4ocGhvdG9zRGlyLCByb3dGaWxlbmFtZSkpXG4gIH0pXG5cbiAgY29uc3QganNvbkZpbGVQYXRoID0gcGF0aC5qb2luKHBob3Rvc0RpciwgYCR7bW9zYWljRmlsZW5hbWV9Lmpzb25gKVxuICBmcy53cml0ZUZpbGVTeW5jKGpzb25GaWxlUGF0aCwgSlNPTi5zdHJpbmdpZnkocGhvdG9CeUlkQWN0ZXVyLCBudWxsLCAyKSlcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmV0cmlldmVQaG90b3NEZXB1dGVzKCk6IFByb21pc2U8bnVtYmVyPiB7XG4gIGNvbnN0IGRhdGFEaXIgPSBvcHRpb25zLmRhdGFEaXJcbiAgY29uc3QgcGhvdG9zUHJlZml4ID0gXCJwaG90b3NfZGVwdXRlc1wiXG4gIGNvbnN0IHBob3Rvc0Rpck5hbWUgPSBgJHtwaG90b3NQcmVmaXh9XyR7b3B0aW9ucy5sZWdpc2xhdHVyZX1gXG4gIGNvbnN0IHBob3Rvc0RpciA9IHBhdGguam9pbihkYXRhRGlyLCBwaG90b3NEaXJOYW1lKVxuICBjb25zdCBwaG90b3NXaWR0aCA9IG9wdGlvbnMud2lkdGhcbiAgY29uc3QgcGhvdG9zSGVpZ2h0ID0gb3B0aW9ucy5oZWlnaHRcbiAgY29uc3QgbWlzc2luZ1Bob3RvRmlsZVBhdGggPSBgaW1hZ2VzL3RyYW5zcGFyZW50XyR7cGhvdG9zV2lkdGh9eCR7cGhvdG9zSGVpZ2h0fS5qcGdgXG5cbiAgY2xvbmVBbmRVcGRhdGVHaXRSZXBvc2l0b3J5KHBob3Rvc0Rpck5hbWUsIG9wdGlvbnMpXG4gIGZzLmVuc3VyZURpclN5bmMocGhvdG9zRGlyKVxuXG4gIGNvbnN0IGFjdGV1clVpZHMgPSBbXVxuICBmb3IgKGNvbnN0IHsgYWN0ZXVyIH0gb2YgaXRlckxvYWRBc3NlbWJsZWVBY3RldXJzKFxuICAgIGRhdGFEaXIsXG4gICAgb3B0aW9ucy5sZWdpc2xhdHVyZSxcbiAgICB7IG5vVmFsaWRhdGlvbjogdHJ1ZSB9LFxuICApKSB7XG4gICAgY29uc3QgeyBtYW5kYXRzIH0gPSBhY3RldXJcbiAgICBpZiAoIW1hbmRhdHMpIGNvbnRpbnVlXG5cbiAgICBjb25zdCBtYW5kYXREZXB1dGUgPSBtYW5kYXRzLmZpbmQoXG4gICAgICAobWFuZGF0OiBNYW5kYXQpID0+XG4gICAgICAgIG1hbmRhdC54c2lUeXBlID09PSBUeXBlTWFuZGF0Lk1hbmRhdFBhcmxlbWVudGFpcmVUeXBlICYmXG4gICAgICAgIG1hbmRhdC5sZWdpc2xhdHVyZSA9PT0gb3B0aW9ucy5sZWdpc2xhdHVyZT8udG9TdHJpbmcoKSAmJlxuICAgICAgICBtYW5kYXQudHlwZU9yZ2FuZSA9PT0gQ29kZVR5cGVPcmdhbmUuQXNzZW1ibGVlLFxuICAgIClcbiAgICBpZiAoIW1hbmRhdERlcHV0ZSkgY29udGludWVcblxuICAgIGNvbnN0IG51bWVyb0RlcHV0ZSA9IGFjdGV1ci51aWQuc3Vic3RyaW5nKDIpXG5cbiAgICAvLyBEb3dubG9hZCBwaG90b3MuXG4gICAgaWYgKG9wdGlvbnMuZmV0Y2gpIHtcbiAgICAgIGNvbnN0IGlkZW50ID0gYWN0ZXVyLmV0YXRDaXZpbC5pZGVudFxuICAgICAgY29uc3QgcGhvdG9GaWxlbmFtZSA9IGAke251bWVyb0RlcHV0ZX0uanBnYFxuICAgICAgY29uc3QgcGhvdG9GaWxlUGF0aCA9IHBhdGguam9pbihwaG90b3NEaXIsIHBob3RvRmlsZW5hbWUpXG4gICAgICBjb25zdCBwaG90b1RlbXBGaWxlbmFtZSA9IGAke251bWVyb0RlcHV0ZX1fdGVtcC5qcGdgXG4gICAgICBjb25zdCBwaG90b1RlbXBGaWxlUGF0aCA9IHBhdGguam9pbihwaG90b3NEaXIsIHBob3RvVGVtcEZpbGVuYW1lKVxuICAgICAgbGV0IHVybFBob3RvID0gYGh0dHA6Ly93d3cyLmFzc2VtYmxlZS1uYXRpb25hbGUuZnIvc3RhdGljL3RyaWJ1bi8ke29wdGlvbnMubGVnaXNsYXR1cmV9L3Bob3Rvcy8ke3Bob3RvRmlsZW5hbWV9YFxuICAgICAgaWYgKG9wdGlvbnMuc3F1YXJlKSB7XG4gICAgICAgIHVybFBob3RvID0gYGh0dHBzOi8vd3d3Mi5hc3NlbWJsZWUtbmF0aW9uYWxlLmZyL3N0YXRpYy90cmlidW4vJHtvcHRpb25zLmxlZ2lzbGF0dXJlfS9waG90b3MvY2FycmUvJHtwaG90b0ZpbGVuYW1lfWBcbiAgICAgIH1cblxuICAgICAgaWYgKCFvcHRpb25zLnNpbGVudCkge1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBgTG9hZGluZyBwaG90byAke3VybFBob3RvfSBmb3IgJHtpZGVudC5wcmVub219ICR7aWRlbnQubm9tfeKApmAsXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgYXdhaXQgZG93bmxvYWRQaG90byhcbiAgICAgICAgdXJsUGhvdG8sXG4gICAgICAgIHBob3RvVGVtcEZpbGVQYXRoLFxuICAgICAgICBwaG90b0ZpbGVQYXRoLFxuICAgICAgICBtaXNzaW5nUGhvdG9GaWxlUGF0aCxcbiAgICAgIClcbiAgICAgIHJlc2l6ZVBob3RvKFxuICAgICAgICBhY3RldXIsXG4gICAgICAgIHBob3Rvc1dpZHRoLFxuICAgICAgICBwaG90b3NIZWlnaHQsXG4gICAgICAgIHBob3Rvc0RpcixcbiAgICAgICAgbnVtZXJvRGVwdXRlLFxuICAgICAgICBvcHRpb25zLFxuICAgICAgKVxuICAgIH1cblxuICAgIGFjdGV1clVpZHMucHVzaChudW1lcm9EZXB1dGUpXG4gIH1cblxuICBjcmVhdGVNb3NhaWMoYWN0ZXVyVWlkcywgcGhvdG9zRGlyLCBwaG90b3NXaWR0aCwgcGhvdG9zSGVpZ2h0LCBcImRlcHV0ZXNcIilcblxuICBpZiAob3B0aW9ucy5jb21taXQpIHtcbiAgICByZXR1cm4gZ2l0LmNvbW1pdEFuZFB1c2gocGhvdG9zRGlyLCBcIk5vdXZlbGxlIG1vaXNzb25cIiwgb3B0aW9ucy5yZW1vdGUpXG4gIH1cbiAgcmV0dXJuIDBcbn1cblxucmV0cmlldmVQaG90b3NEZXB1dGVzKClcbiAgLnRoZW4oKGV4aXRDb2RlKSA9PiBwcm9jZXNzLmV4aXQoZXhpdENvZGUpKVxuICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgY29uc29sZS5sb2coZXJyb3IpXG4gICAgcHJvY2Vzcy5leGl0KDEpXG4gIH0pXG4iXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLFFBQVEsUUFBUSxlQUFlO0FBQ3hDLE9BQU9DLGVBQWUsTUFBTSxtQkFBbUI7QUFDL0MsT0FBT0MsRUFBRSxNQUFNLFVBQVU7QUFDekIsT0FBT0MsSUFBSSxNQUFNLE1BQU07QUFDdkIsT0FBT0MsTUFBTSxNQUFNLFFBQVE7QUFDM0IsT0FBT0MsSUFBSSxNQUFNLE1BQU07QUFBQSxPQUNoQixLQUFLQyxHQUFHO0FBQUEsU0FFTkMsd0JBQXdCO0FBQUEsU0FHL0JDLGNBQWMsRUFHZEMsVUFBVTtBQUFBLFNBR1ZDLFdBQVcsRUFDWEMsWUFBWSxFQUNaQyxZQUFZLEVBQ1pDLFlBQVksRUFDWkMsb0JBQW9CLEVBQ3BCQyxVQUFVLEVBQ1ZDLGlCQUFpQixFQUNqQkMsV0FBVztBQUdiLE1BQU1DLGtCQUFrQixHQUFHLENBQ3pCUixXQUFXLEVBQ1hDLFlBQVksRUFDWkMsWUFBWSxFQUNaQyxZQUFZLEVBQ1pDLG9CQUFvQixFQUNwQkMsVUFBVSxFQUNWRSxXQUFXLEVBQ1hELGlCQUFpQixFQUNqQjtFQUNFRyxLQUFLLEVBQUUsR0FBRztFQUNWQyxZQUFZLEVBQUUsS0FBSztFQUNuQkMsSUFBSSxFQUFFLFFBQVE7RUFDZEMsSUFBSSxFQUFFQztBQUNSLENBQUMsRUFDRDtFQUNFSixLQUFLLEVBQUUsR0FBRztFQUNWQyxZQUFZLEVBQUUsR0FBRztFQUNqQkMsSUFBSSxFQUFFLE9BQU87RUFDYkMsSUFBSSxFQUFFRTtBQUNSLENBQUMsRUFDRDtFQUNFTCxLQUFLLEVBQUUsR0FBRztFQUNWQyxZQUFZLEVBQUUsR0FBRztFQUNqQkMsSUFBSSxFQUFFLFFBQVE7RUFDZEMsSUFBSSxFQUFFRTtBQUNSLENBQUMsQ0FDRjtBQUNELE1BQU1DLE9BQU8sR0FBR3hCLGVBQWUsQ0FBQ2lCLGtCQUFrQixDQUFDO0FBRW5ELE9BQU8sU0FBU1EsMkJBQTJCQSxDQUN6Q0Ms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