UNPKG

indexnow-submit

Version:

CLI tool to use IndexNow to notify search engines of website changes

185 lines 21 kB
import * as fs from 'fs'; import got from 'got'; import Sitemapper from 'sitemapper'; // import { default as SitemapXMLParser } from 'sitemap-xml-parser'; import { parse, toSeconds } from "iso8601-duration"; import { default as FeedMe } from 'feedme'; /** * Use Axios to post a URL list via IndexNow to the given search engine. * * @param key The authentication key to use for IndexNow * @param engine The domain name for the search engine * @param host The domain name for your website * @param urlList The list of URLs to post to IndexNow */ export async function postURLlist(engine, host, key, urlList) { const u = indexNowURL(engine); try { // POST /indexnow HTTP/1.1 // Content-Type: application/json; charset=utf-8 // Host: <searchengine> // { // "host": "www.example.com", // "key": "aaa6c957e47d498589ee7a33281997cb", // "keyLocation": "https://www.example.com/myIndexNowKey63638.txt", // "urlList": [ // "https://www.example.com/url1", // "https://www.example.com/folder/url2", // "https://www.example.com/url3" // ] // } const response = await got.post(u.toString(), { // headers: { // 'Content-Type': 'application/json; charset=utf-8' // }, json: { host: host, key: key, urlList: urlList } }); console.log(`Submitted ${urlList.length} URL's to ${engine} status ${response.statusCode}`); } catch (err) { console.error(err); } } /** * Submit a single URL to an IndexNow service. If this executes with * no error it was successful. Otherwise a suitable error is thrown. * * @param engine The domain name of the search engine * @param url The URL to submit * @param key The IndexNow key to use */ export async function submitSingleURL(engine, url, key) { // https://<searchengine>/indexnow?url=url-changed&key=your-key const u = indexNowURL(engine); u.searchParams.append('url', url); u.searchParams.append('key', key); console.log(`Submitting ${u.toString()}`); const response = await got.get(u.toString()); console.log(`Submitted to ${engine} ${url} status ${response.statusCode}`); } /** * Generate a URL obect for the IndexNow service on the given * search engine. * @param engine The domain name for the search engine * @returns */ export function indexNowURL(engine) { const u = new URL(`https://ENGINE/indexnow`); u.host = engine; return u; } /** * Fetches all items from a sitemap, accodomating sitemaps that have * sub-sitemaps. The return value is an array of {SitemapEntry}. * * @param u The URL for the sitemap * @param maxAge Optional, an ISO8601 descriptor a maximum age, so we * can select recently created items. e.g. P10D means 10 days * @returns */ export async function fetchURLsFromSitemap(u, maxAge) { if (!u) throw new Error(`No URL given ${u}`); // console.log(`fetchURLsFromSitemap ${u} ${maxAge}`); const sitemapXMLParser = new Sitemapper({ url: u, timeout: 15000, fields: { loc: true, lastmod: true, changefreq: true, priority: true, } }); // const sitemapXMLParser = new SitemapXMLParser(u, { // delay: 3000, // limit: 5 // }); // console.log(`fetching`); const items = await sitemapXMLParser.fetch(); const ret = new Array(); for (const item of items.sites) { if (typeof item === 'string') { ret.push({ loc: [item] }); } else if (typeof item === 'object') { const anyitem = item; if (typeof anyitem.loc === 'string') { anyitem.loc = [anyitem.loc]; } ret.push(anyitem); } } return ret; // return items; // if (maxAge) { // const now = new Date(); // const maxSecs = toSeconds(parse(maxAge)); // // console.log(`maxAge ${maxAge} maxSecs ${maxSecs}`); // return items.sites; // // .filter(item => { // // const lastmod = new Date(item.lastmod); // // const age = now.getTime() - lastmod.getTime(); // // return (age / 1000) < maxSecs; // // }); // } else { // return items.sites; // } } /** * Retrieve URLs from the RSS or Atom file, returning as * an array. * * @param feedURL The URL for the RSS or Atom feed * @param maxAge An ISO8601 duration string as discussed above * @returns */ export async function fetchURLsFromRSSAtom(feedURL, maxAge) { const uFeed = new URL(feedURL); let feed; try { // Support reading the RSS file either from a file or // over the Internet let rssStream; if (uFeed.protocol === 'file:') { rssStream = fs.createReadStream(uFeed.pathname, 'utf-8'); } else { const resFeed = await got.stream(feedURL); rssStream = resFeed; } feed = await new Promise((resolve, reject) => { try { let parser = new FeedMe(true); parser.on('finish', () => { resolve(parser.done()); }); rssStream.pipe(parser); } catch (err) { reject(err); } }); } catch (err) { throw new Error(`Fetching feed ${feedURL} failed because ${err.message}`); } const urlList = []; for (const item of feed.items) { if (maxAge) { const now = new Date(); const maxSecs = toSeconds(parse(maxAge)); const pubdate = new Date(item.pubdate); const age = now.getTime() - pubdate.getTime(); if ((age / 1000) > maxSecs) continue; } urlList.push(item.link); } return urlList; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9saWIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxHQUE2QixNQUFNLEtBQUssQ0FBQztBQUNoRCxPQUFPLFVBQVUsTUFBTSxZQUFZLENBQUM7QUFDcEMsb0VBQW9FO0FBQ3BFLE9BQU8sRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDcEQsT0FBTyxFQUFFLE9BQU8sSUFBSSxNQUFNLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFFM0M7Ozs7Ozs7R0FPRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsV0FBVyxDQUM3QixNQUFjLEVBQUUsSUFBWSxFQUM1QixHQUFXLEVBQUcsT0FBc0I7SUFHcEMsTUFBTSxDQUFDLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRTlCLElBQUk7UUFFQSwwQkFBMEI7UUFDMUIsZ0RBQWdEO1FBQ2hELHVCQUF1QjtRQUN2QixJQUFJO1FBQ0osaUNBQWlDO1FBQ2pDLGlEQUFpRDtRQUNqRCx1RUFBdUU7UUFDdkUsbUJBQW1CO1FBQ25CLDBDQUEwQztRQUMxQyxpREFBaUQ7UUFDakQseUNBQXlDO1FBQ3pDLFFBQVE7UUFDUixJQUFJO1FBRUosTUFBTSxRQUFRLEdBQWtCLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7WUFDekQsYUFBYTtZQUNiLHdEQUF3RDtZQUN4RCxLQUFLO1lBQ0wsSUFBSSxFQUFFO2dCQUNGLElBQUksRUFBRSxJQUFJO2dCQUNWLEdBQUcsRUFBRSxHQUFHO2dCQUNSLE9BQU8sRUFBRSxPQUFPO2FBQ25CO1NBQ2UsQ0FBQyxDQUFDO1FBQ3RCLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxPQUFPLENBQUMsTUFBTSxhQUFhLE1BQU0sV0FBVyxRQUFRLENBQUMsVUFB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R0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7S0FDN0U7SUFFRCxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUM7SUFDbkIsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFO1FBQzNCLElBQUksTUFBTSxFQUFFO1lBQ1IsTUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUN2QixNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDekMsTUFBTSxPQUFPLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3ZDLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDOUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxPQUFPO2dCQUFFLFNBQVM7U0FDeEM7UUFDRCxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUMzQjtJQUVELE9BQU8sT0FBTyxDQUFDO0FBQ25CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCB7IHByb21pc2VzIGFzIGZzcCB9IGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCBnb3QsIHsgUmVzcG9uc2UsIEdvdE9wdGlvbnMgfSBmcm9tICdnb3QnO1xuaW1wb3J0IFNpdGVtYXBwZXIgZnJvbSAnc2l0ZW1hcHBlcic7XG4vLyBpbXBvcnQgeyBkZWZhdWx0IGFzIFNpdGVtYXBYTUxQYXJzZXIgfSBmcm9tICdzaXRlbWFwLXhtbC1wYXJzZXInO1xuaW1wb3J0IHsgcGFyc2UsIHRvU2Vjb25kcyB9IGZyb20gXCJpc284NjAxLWR1cmF0aW9uXCI7XG5pbXBvcnQgeyBkZWZhdWx0IGFzIEZlZWRNZSB9IGZyb20gJ2ZlZWRtZSc7XG5cbi8qKlxuICogVXNlIEF4aW9zIHRvIHBvc3QgYSBVUkwgbGlzdCB2aWEgSW5kZXhOb3cgdG8gdGhlIGdpdmVuIHNlYXJjaCBlbmdpbmUuXG4gKiBcbiAqIEBwYXJhbSBrZXkgVGhlIGF1dGhlbnRpY2F0aW9uIGtleSB0byB1c2UgZm9yIEluZGV4Tm93XG4gKiBAcGFyYW0gZW5naW5lIFRoZSBkb21haW4gbmFtZSBmb3IgdGhlIHNlYXJjaCBlbmdpbmVcbiAqIEBwYXJhbSBob3N0IFRoZSBkb21haW4gbmFtZSBmb3IgeW91ciB3ZWJzaXRlXG4gKiBAcGFyYW0gdXJsTGlzdCBUaGUgbGlzdCBvZiBVUkxzIHRvIHBvc3QgdG8gSW5kZXhOb3dcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBvc3RVUkxsaXN0KFxuICAgIGVuZ2luZTogc3RyaW5nLCBob3N0OiBzdHJpbmcsXG4gICAga2V5OiBzdHJpbmcsICB1cmxMaXN0OiBBcnJheTxzdHJpbmc+XG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBcbiAgICBjb25zdCB1ID0gaW5kZXhOb3dVUkwoZW5naW5lKTtcblxuICAgIHRyeSB7XG5cbiAgICAgICAgLy8gUE9TVCAvaW5kZXhub3cgSFRUUC8xLjFcbiAgICAgICAgLy8gQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uOyBjaGFyc2V0PXV0Zi04XG4gICAgICAgIC8vIEhvc3Q6IDxzZWFyY2hlbmdpbmU+XG4gICAgICAgIC8vIHtcbiAgICAgICAgLy8gICAgIFwiaG9zdFwiOiBcInd3dy5leGFtcGxlLmNvbVwiLFxuICAgICAgICAvLyAgICAgXCJrZXlcIjogXCJhYWE2Yzk1N2U0N2Q0OTg1ODllZTdhMzMyODE5OTdjYlwiLFxuICAgICAgICAvLyAgICAgXCJrZXlMb2NhdGlvblwiOiBcImh0dHBzOi8vd3d3LmV4YW1wbGUuY29tL215SW5kZXhOb3dLZXk2MzYzOC50eHRcIixcbiAgICAgICAgLy8gICAgIFwidXJsTGlzdFwiOiBbXG4gICAgICAgIC8vICAgICAgICAgXCJodHRwczovL3d3dy5leGFtcGxlLmNvbS91cmwxXCIsXG4gICAgICAgIC8vICAgICAgICAgXCJodHRwczovL3d3dy5leGFtcGxlLmNvbS9mb2xkZXIvdXJsMlwiLFxuICAgICAgICAvLyAgICAgICAgIFwiaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20vdXJsM1wiXG4gICAgICAgIC8vICAgICBdXG4gICAgICAgIC8vIH1cblxuICAgICAgICBjb25zdCByZXNwb25zZTogUmVzcG9uc2U8YW55PiA9IGF3YWl0IGdvdC5wb3N0KHUudG9TdHJpbmcoKSwge1xuICAgICAgICAgICAgLy8gaGVhZGVyczoge1xuICAgICAgICAgICAgLy8gICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOCdcbiAgICAgICAgICAgIC8vIH0sXG4gICAgICAgICAgICBqc29uOiB7XG4gICAgICAgICAgICAgICAgaG9zdDogaG9zdCxcbiAgICAgICAgICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgICAgICAgICB1cmxMaXN0OiB1cmxMaXN0XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gYXMgR290T3B0aW9uczxhbnk+KTtcbiAgICAgICAgY29uc29sZS5sb2coYFN1Ym1pdHRlZCAke3VybExpc3QubGVuZ3RofSBVUkwncyB0byAke2VuZ2luZX0gc3RhdHVzICR7cmVzcG9uc2Uuc3RhdHVzQ29kZX1gKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBTdWJtaXQgYSBzaW5nbGUgVVJMIHRvIGFuIEluZGV4Tm93IHNlcnZpY2UuICBJZiB0aGlzIGV4ZWN1dGVzIHdpdGhcbiAqIG5vIGVycm9yIGl0IHdhcyBzdWNjZXNzZnVsLiAgT3RoZXJ3aXNlIGEgc3VpdGFibGUgZXJyb3IgaXMgdGhyb3duLlxuICogXG4gKiBAcGFyYW0gZW5naW5lIFRoZSBkb21haW4gbmFtZSBvZiB0aGUgc2VhcmNoIGVuZ2luZVxuICogQHBhcmFtIHVybCBUaGUgVVJMIHRvIHN1Ym1pdFxuICogQHBhcmFtIGtleSBUaGUgSW5kZXhOb3cga2V5IHRvIHVzZVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3VibWl0U2luZ2xlVVJMKFxuICAgIGVuZ2luZTogc3RyaW5nLCB1cmw6IHN0cmluZywga2V5OiBzdHJpbmdcbik6IFByb21pc2U8dm9pZD4ge1xuXG4gICAgLy8gaHR0cHM6Ly88c2VhcmNoZW5naW5lPi9pbmRleG5vdz91cmw9dXJsLWNoYW5nZWQma2V5PXlvdXIta2V5XG5cbiAgICBjb25zdCB1ID0gaW5kZXhOb3dVUkwoZW5naW5lKTtcblxuICAgIHUuc2VhcmNoUGFyYW1zLmFwcGVuZCgndXJsJywgdXJsKTtcbiAgICB1LnNlYXJjaFBhcmFtcy5hcHBlbmQoJ2tleScsIGtleSk7XG5cbiAgICBjb25zb2xlLmxvZyhgU3VibWl0dGluZyAke3UudG9TdHJpbmcoKX1gKTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZ290LmdldCh1LnRvU3RyaW5nKCkpO1xuXG4gICAgY29uc29sZS5sb2coYFN1Ym1pdHRlZCB0byAke2VuZ2luZX0gJHt1cmx9IHN0YXR1cyAke3Jlc3BvbnNlLnN0YXR1c0NvZGV9YCk7XG59XG5cbi8qKlxuICogR2VuZXJhdGUgYSBVUkwgb2JlY3QgZm9yIHRoZSBJbmRleE5vdyBzZXJ2aWNlIG9uIHRoZSBnaXZlbiBcbiAqIHNlYXJjaCBlbmdpbmUuIFxuICogQHBhcmFtIGVuZ2luZSBUaGUgZG9tYWluIG5hbWUgZm9yIHRoZSBzZWFyY2ggZW5naW5lXG4gKiBAcmV0dXJucyBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluZGV4Tm93VVJMKGVuZ2luZTogc3RyaW5nKTogVVJMIHtcblxuICAgIGNvbnN0IHUgPSBuZXcgVVJMKGBodHRwczovL0VOR0lORS9pbmRleG5vd2ApO1xuICAgIHUuaG9zdCA9IGVuZ2luZTtcbiAgICByZXR1cm4gdTtcbn1cblxuLyoqXG4gKiBEZXNjcmliZXMgU2l0ZW1hcCBlbnRyaWVzIFxuICovXG5leHBvcnQgdHlwZSBTaXRlbWFwRW50cnkgPSB7XG4gICAgLyoqXG4gICAgICogVVJMKHMpIGZvciBhbiBpdGVtIGluIHRoZSBTaXRlbWFwXG4gICAgICovXG4gICAgbG9jOiBBcnJheTxzdHJpbmc+LFxuXG4gICAgLyoqXG4gICAgICogTGFzdCBtb2RpZmljYXRpb24gZGF0ZShzKVxuICAgICAqL1xuICAgIGxhc3Rtb2Q/OiBBcnJheTxzdHJpbmc+LFxuXG4gICAgLyoqXG4gICAgICogSG93IG9mdGVuIHRvIGV4cGVjdCB0aGlzIGl0ZW0gdG8gY2hhbmdlXG4gICAgICovXG4gICAgY2hhbmdlZnJlcT86IEFycmF5PHN0cmluZz4sXG5cbiAgICAvKipcbiAgICAgKiBQcmlvcml0aXphdGlvblxuICAgICAqL1xuICAgIHByaW9yaXR5PzogQXJyYXk8c3RyaW5nPixcbiAgICBpbWFnZT86IEFycmF5PHN0cmluZz5cbn07XG5cbi8qKlxuICogRmV0Y2hlcyBhbGwgaXRlbXMgZnJvbSBhIHNpdGVtYXAsIGFjY29kb21hdGluZyBzaXRlbWFwcyB0aGF0IGhhdmVcbiAqIHN1Yi1zaXRlbWFwcy4gIFRoZSByZXR1cm4gdmFsdWUgaXMgYW4gYXJyYXkgb2Yge1NpdGVtYXBFbnRyeX0uXG4gKiBcbiAqIEBwYXJhbSB1IFRoZSBVUkwgZm9yIHRoZSBzaXRlbWFwXG4gKiBAcGFyYW0gbWF4QWdlIE9wdGlvbmFsLCBhbiBJU084NjAxIGRlc2NyaXB0b3IgYSBtYXhpbXVtIGFnZSwgc28gd2VcbiAqICAgIGNhbiBzZWxlY3QgcmVjZW50bHkgY3JlYXRlZCBpdGVtcy4gIGUuZy4gUDEwRCBtZWFucyAxMCBkYXlzXG4gKiBAcmV0dXJucyBcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZldGNoVVJMc0Zyb21TaXRlbWFwKFxuICAgIHU6IHN0cmluZywgbWF4QWdlPzogc3RyaW5nXG4pIDogUHJvbWlzZTxBcnJheTxTaXRlbWFwRW50cnk+Plxue1xuXG4gICAgaWYgKCF1KSB0aHJvdyBuZXcgRXJyb3IoYE5vIFVSTCBnaXZlbiAke3V9YCk7XG5cbiAgICAvLyBjb25zb2xlLmxvZyhgZmV0Y2hVUkxzRnJvbVNpdGVtYXAgJHt1fSAke21heEFnZX1gKTtcblxuICAgIGNvbnN0IHNpdGVtYXBYTUxQYXJzZXIgPSBuZXcgU2l0ZW1hcHBlcih7XG4gICAgICAgIHVybDogdSxcbiAgICAgICAgdGltZW91dDogMTUwMDAsIC8vIDE1IHNlY29uZHNcbiAgICAgICAgZmllbGRzOiB7XG4gICAgICAgICAgICBsb2M6IHRydWUsXG4gICAgICAgICAgICBsYXN0bW9kOiB0cnVlLFxuICAgICAgICAgICAgY2hhbmdlZnJlcTogdHJ1ZSxcbiAgICAgICAgICAgIHByaW9yaXR5OiB0cnVlLFxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAvLyBjb25zdCBzaXRlbWFwWE1MUGFyc2VyID0gbmV3IFNpdGVtYXBYTUxQYXJzZXIodSwge1xuICAgIC8vICAgICBkZWxheTogMzAwMCxcbiAgICAvLyAgICAgbGltaXQ6IDVcbiAgICAvLyB9KTtcblxuICAgIC8vIGNvbnNvbGUubG9nKGBmZXRjaGluZ2ApO1xuXG4gICAgY29uc3QgaXRlbXMgPSBhd2FpdCBzaXRlbWFwWE1MUGFyc2VyLmZldGNoKCk7XG4gICAgY29uc3QgcmV0ID0gbmV3IEFycmF5PFNpdGVtYXBFbnRyeT4oKTtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMuc2l0ZXMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0LnB1c2goeyBsb2M6IFsgaXRlbSBdIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBpdGVtID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgY29uc3QgYW55aXRlbTogYW55ID0gPGFueT5pdGVtO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBhbnlpdGVtLmxvYyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBhbnlpdGVtLmxvYyA9IFsgYW55aXRlbS5sb2MgXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldC5wdXNoKGFueWl0ZW0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gICAgLy8gcmV0dXJuIGl0ZW1zO1xuXG4gICAgLy8gaWYgKG1heEFnZSkge1xuICAgIC8vICAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuXG4gICAgLy8gICAgIGNvbnN0IG1heFNlY3MgPSB0b1NlY29uZHMocGFyc2UobWF4QWdlKSk7XG4gICAgLy8gICAgIC8vIGNvbnNvbGUubG9nKGBtYXhBZ2UgJHttYXhBZ2V9IG1heFNlY3MgJHttYXhTZWNzfWApO1xuXG4gICAgLy8gICAgIHJldHVybiBpdGVtcy5zaXRlcztcbiAgICAvLyAgICAgLy8gLmZpbHRlcihpdGVtID0+IHtcbiAgICAvLyAgICAgLy8gICAgIGNvbnN0IGxhc3Rtb2QgPSBuZXcgRGF0ZShpdGVtLmxhc3Rtb2QpO1xuICAgIC8vICAgICAvLyAgICAgY29uc3QgYWdlID0gbm93LmdldFRpbWUoKSAtIGxhc3Rtb2QuZ2V0VGltZSgpO1xuICAgIC8vICAgICAvLyAgICAgcmV0dXJuIChhZ2UgLyAxMDAwKSA8IG1heFNlY3M7XG4gICAgLy8gICAgIC8vIH0pO1xuICAgIC8vIH0gZWxzZSB7XG4gICAgLy8gICAgIHJldHVybiBpdGVtcy5zaXRlcztcbiAgICAvLyB9XG4gICAgXG59XG5cbi8qKlxuICogUmV0cmlldmUgVVJMcyBmcm9tIHRoZSBSU1Mgb3IgQXRvbSBmaWxlLCByZXR1cm5pbmcgYXNcbiAqIGFuIGFycmF5LlxuICogXG4gKiBAcGFyYW0gZmVlZFVSTCAgVGhlIFVSTCBmb3IgdGhlIFJTUyBvciBBdG9tIGZlZWRcbiAqIEBwYXJhbSBtYXhBZ2UgQW4gSVNPODYwMSBkdXJhdGlvbiBzdHJpbmcgYXMgZGlzY3Vzc2VkIGFib3ZlXG4gKiBAcmV0dXJucyBcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZldGNoVVJMc0Zyb21SU1NBdG9tKFxuICAgIGZlZWRVUkw6IHN0cmluZywgbWF4QWdlOiBzdHJpbmdcbik6IFByb21pc2U8QXJyYXk8c3RyaW5nPj4ge1xuXG4gICAgY29uc3QgdUZlZWQgPSBuZXcgVVJMKGZlZWRVUkwpO1xuXG4gICAgbGV0IGZlZWQ7XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gU3VwcG9ydCByZWFkaW5nIHRoZSBSU1MgZmlsZSBlaXRoZXIgZnJvbSBhIGZpbGUgb3IgXG4gICAgICAgIC8vIG92ZXIgdGhlIEludGVybmV0XG4gICAgICAgIGxldCByc3NTdHJlYW07XG4gICAgICAgIGlmICh1RmVlZC5wcm90b2NvbCA9PT0gJ2ZpbGU6Jykge1xuICAgICAgICAgICAgcnNzU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbSh1RmVlZC5wYXRobmFtZSwgJ3V0Zi04Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCByZXNGZWVkID0gYXdhaXQgZ290LnN0cmVhbShmZWVkVVJMKTtcbiAgICAgICAgICAgIHJzc1N0cmVhbSA9IHJlc0ZlZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBmZWVkID0gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgcGFyc2VyID0gbmV3IEZlZWRNZSh0cnVlKTtcbiAgICAgICAgICAgICAgICBwYXJzZXIub24oJ2ZpbmlzaCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShwYXJzZXIuZG9uZSgpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByc3NTdHJlYW0ucGlwZShwYXJzZXIpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7IHJlamVjdChlcnIpOyB9XG4gICAgICAgIH0pO1xuICAgIH0gY2F0Y2goZXJyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmV0Y2hpbmcgZmVlZCAke2ZlZWRVUkx9IGZhaWxlZCBiZWNhdXNlICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgdXJsTGlzdCA9IFtdO1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiBmZWVkLml0ZW1zKSB7XG4gICAgICAgIGlmIChtYXhBZ2UpIHtcbiAgICAgICAgICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgICAgICAgICBjb25zdCBtYXhTZWNzID0gdG9TZWNvbmRzKHBhcnNlKG1heEFnZSkpO1xuICAgICAgICAgICAgY29uc3QgcHViZGF0ZSA9IG5ldyBEYXRlKGl0ZW0ucHViZGF0ZSk7XG4gICAgICAgICAgICBjb25zdCBhZ2UgPSBub3cuZ2V0VGltZSgpIC0gcHViZGF0ZS5nZXRUaW1lKCk7XG4gICAgICAgICAgICBpZiAoKGFnZSAvIDEwMDApID4gbWF4U2VjcykgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgdXJsTGlzdC5wdXNoKGl0ZW0ubGluayk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHVybExpc3Q7XG59Il19