import { getData, addData, addDataArray } from "./db.js"; // let posts:any; // let keyBase = "dandelion_posts_v1_" // let key:string = ""; // interface PostTimestamp { // year: number, // month: number, // day: number, // hour: number, // minute: number, // second: number, // } class Post { constructor(author, author_id, text, post_timestamp, imageData = null, importedFrom = null, importSource = null) { this.post_timestamp = post_timestamp; this.author = author; this.author_id = author_id; this.text = text; this.image_data = imageData; this.importedFrom = importedFrom; this.importSource = importSource; } } function initMarkdown() { const renderer = new marked.Renderer(); renderer.link = (href, title, text) => { return `${text}`; }; marked.setOptions({ renderer: renderer }); } function waitMs(durationMs) { return new Promise(resolve => setTimeout(resolve, durationMs)); } function uuidv4() { return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)); } let logLines = []; let logLength = 10; function log(message) { logLines.push(`${new Date().toLocaleTimeString()}: ${message}`); if (logLines.length > 10) { logLines = logLines.slice(logLines.length - logLength); } let log = document.getElementById("log"); if (!log) { throw new Error(); } log.innerText = logLines.join("\n"); } function arrayBufferToBase64(buffer) { return new Promise((resolve, reject) => { const blob = new Blob([buffer], { type: 'application/octet-stream' }); const reader = new FileReader(); reader.onloadend = () => { const dataUrl = reader.result; if (!dataUrl) { resolve(null); return; } const base64 = dataUrl.split(',')[1]; resolve(base64); }; reader.onerror = (error) => { reject(error); }; reader.readAsDataURL(blob); }); } async function createTestData() { let postsTestData = await (await fetch("./postsTestData.json")).json(); return postsTestData; } let time = 0; function timerStart() { time = performance.now(); } function timerDelta() { return performance.now() - time; } async function getFixedTweetText(entry) { let fullText = entry.tweet.full_text; let linkMarkdown = ""; for (const url of entry.tweet.entities.urls) { linkMarkdown = `[${url.display_url}](${url.expanded_url})`; fullText = fullText.replace(url.url, linkMarkdown); } return fullText; } async function createTestData2(userID) { log("Importing tweet archive"); let postsTestData = []; let response = await fetch("./tweets.js"); let tweetsText = await response.text(); tweetsText = tweetsText.replace("window.YTD.tweets.part0", "window.tweetData"); new Function(tweetsText)(); // let tweets = JSON.parse(tweetJSON); let count = 0; for (let entry of window.tweetData) { // if (entry.tweet.hasOwnProperty("in_reply_to_screen_name") || entry.tweet.retweeted || entry.tweet.full_text.startsWith("RT")) { // continue; // } let mediaURL = entry.tweet?.entities?.media?.[0]?.media_url; let isImage = false; if (mediaURL) { isImage = mediaURL.includes('jpg'); } let imageData = null; if (isImage) { try { let response = await fetch(mediaURL); await waitMs(100); if (response.status === 200) { imageData = await response.arrayBuffer(); } console.log(imageData); } catch (e) { console.log(e); } } let timeStamp = new Date(entry.tweet.created_at); let tweetText = await getFixedTweetText(entry); let newPost = new Post('bobbydigitales', userID, tweetText, timeStamp, imageData, 'twitter', entry); postsTestData.push(newPost); count++; if (count % 100 === 0) { log(`Imported ${count} posts...`); // render(postsTestData); } // if (count == 100-1) { // break; // } } return postsTestData; } async function createTestData3(userID) { let posts = await (await (fetch('./posts.json'))).json(); return posts; } async function registerServiceWorker() { if (!("serviceWorker" in navigator)) { return; } let registrations = await navigator.serviceWorker.getRegistrations(); if (registrations.length > 0) { console.log("Service worker already registered."); return registrations[0]; } navigator.serviceWorker .register("/sw.js") .then((registration) => { console.log("Service Worker registered with scope:", registration.scope); return registration; }) .catch((error) => { console.error("Service Worker registration failed:", error); }); } function addPost(userID, posts, postText) { if ((typeof postText !== "string") || postText.length === 0) { log("Not posting an empty string..."); return; } let post = new Post(`bobbydigitales`, userID, postText, new Date()); posts.push(post); // localStorage.setItem(key, JSON.stringify(posts)); addData(userID, post); render(posts); } function generateID() { if (self.crypto.hasOwnProperty("randomUUID")) { return self.crypto.randomUUID(); } return uuidv4(); } function getUserID() { let id = localStorage.getItem("dandelion_id"); if (!id) { id = generateID(); localStorage.setItem("dandelion_id", id); } return id; } function connectWebsocket(userID) { let websocket = new WebSocket(`ws://${window.location.hostname}:${window.location.port}/ws`); websocket.onopen = function (evt) { log("Websocket: CONNECTED"); websocket.send(`{"messageType":"connect", "id": "${userID}"}`); }; websocket.onclose = function (evt) { log("Websocket: DISCONNECTED"); }; websocket.onmessage = function (evt) { log('Websocket: RESPONSE: ' + evt.data); }; websocket.onerror = function (evt) { log('Websocket: ERROR: ' + evt); }; return websocket; } function setFont(fontName) { document.body.style.fontFamily = fontName; let textArea = document.getElementById('textarea_post'); if (!textArea) { return; } textArea.style.fontFamily = fontName; } function initOffline() { // Event listener for going offline window.addEventListener('offline', () => { log("offline"); }); // Event listener for going online window.addEventListener('online', () => { log("online"); }); log(`Online status: ${navigator.onLine ? "online" : "offline"}`); } function initButtons(userID, posts) { let font1Button = document.getElementById("button_font1"); let font2Button = document.getElementById("button_font2"); font1Button.addEventListener('click', () => { setFont('Bookerly'); }); font2Button.addEventListener('click', () => { setFont('Virgil'); }); let postButton = document.getElementById("button_post"); let postText = document.getElementById("textarea_post"); if (!(postButton && postText)) { throw new Error(); } postButton.addEventListener("click", () => { addPost(userID, posts, postText.value); postText.value = ""; }); } async function loadPosts(userID) { timerStart(); let posts = await getData(userID, new Date(2022, 8), new Date()); if (posts.length > 0) { log(`Loaded ${posts.length} posts in ${timerDelta().toFixed(2)}ms`); return posts; } posts = await createTestData2(userID); log("Adding test data..."); addDataArray(userID, posts); return await getData(userID, new Date(2022, 8), new Date()); } async function main() { let posts = []; let time = 0; ``; let delta = 0; let urlParams = (new URL(window.location.href)).searchParams; if (urlParams.get("sw") === "true") { let registration = await registerServiceWorker(); } let userID = getUserID(); log(`Your user ID is: ${userID}`); if (navigator.storage && navigator.storage.persist && !navigator.storage.persisted) { const isPersisted = await navigator.storage.persist(); log(`Persisted storage granted: ${isPersisted}`); } log(`Persisted: ${(await navigator.storage.persisted()).toString()}`); initMarkdown(); // let main = await fetch("/main.js"); // let code = await main.text(); // console.log(code); // registration.active.postMessage({type:"updateMain", code:code}); posts = await loadPosts(userID); let websocket = connectWebsocket(userID); initOffline(); initButtons(userID, posts); // debugger; timerStart(); render(posts); let renderTime = timerDelta(); log(`render took: ${renderTime.toFixed(2)}ms`); log(`memory used: ${(performance.memory.usedJSHeapSize / 1024 / 1024).toFixed(2)}Mb`); } function render(posts) { const fragment = document.createDocumentFragment(); let contentDiv = document.getElementById("content"); if (!contentDiv) { throw new Error(); } contentDiv.innerHTML = ""; let count = 0; for (let i = posts.length - 1; i >= 0; i--) { let postData = posts[i]; let post = renderPost(postData); if (post) { fragment.appendChild(post); count++; } if (count > 100) { break; } } if (!contentDiv) { throw new Error("Couldn't get content div!"); } contentDiv.appendChild(fragment); } function renderPost(post) { if (!(post.hasOwnProperty("text"))) { throw new Error("Post is malformed!"); } let containerDiv = document.createElement("div"); let textDiv = document.createElement("div"); let timestampDiv = document.createElement("div"); let hr = document.createElement("hr"); textDiv.innerHTML = marked.parse(post.text); // textDiv.innerHTML = DOMPurify.sanitize(marked.parse(post.text)); timestampDiv.innerText = `${post.post_timestamp.toDateString()}`; timestampDiv.title = `${post.post_timestamp.toLocaleTimeString()} ยท ${post.post_timestamp.toDateString()}`; containerDiv.appendChild(hr); containerDiv.appendChild(textDiv); if (!("image_data" in post && post.image_data)) { containerDiv.appendChild(timestampDiv); return containerDiv; // return null; } let image = document.createElement("img"); const blob = new Blob([post.image_data], { type: 'image/jpg' }); const url = URL.createObjectURL(blob); image.onload = () => { URL.revokeObjectURL(url); }; image.src = url; // image.src = image.src = "data:image/png;base64," + post.image; image.className = "postImage"; containerDiv.appendChild(image); containerDiv.appendChild(timestampDiv); return containerDiv; } window.addEventListener("load", main); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBZ0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxTQUFTLENBQUE7QUFHdEUsaUJBQWlCO0FBQ2pCLHNDQUFzQztBQUN0Qyx1QkFBdUI7QUFFdkIsNEJBQTRCO0FBQzVCLGtCQUFrQjtBQUNsQixtQkFBbUI7QUFDbkIsaUJBQWlCO0FBQ2pCLGtCQUFrQjtBQUNsQixvQkFBb0I7QUFDcEIsb0JBQW9CO0FBQ3BCLElBQUk7QUFFSixNQUFNLElBQUk7SUFXUixZQUFZLE1BQWMsRUFBRSxTQUFpQixFQUFFLElBQVksRUFBRSxjQUFvQixFQUFFLFlBQWdDLElBQUksRUFBRSxlQUFpQyxJQUFJLEVBQUUsZUFBb0IsSUFBSTtRQUN0TCxJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztRQUVyQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztRQUU1QixJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztRQUNqQyxJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztJQUNuQyxDQUFDO0NBQ0Y7QUFHRCxTQUFTLFlBQVk7SUFDbkIsTUFBTSxRQUFRLEdBQUcsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDdkMsUUFBUSxDQUFDLElBQUksR0FBRyxDQUFDLElBQVMsRUFBRSxLQUFhLEVBQUUsSUFBWSxFQUFFLEVBQUU7UUFDekQsT0FBTyxZQUFZLElBQUksb0JBQW9CLEtBQUssQ0FBQyxDQUFDLENBQUMsV0FBVyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLElBQUks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QixZQUFZLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2hDLFlBQVksQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLENBQUM7SUFFdkMsT0FBTyxZQUFZLENBQUM7QUFDdEIsQ0FBQztBQUVELE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBvcGVuRGF0YWJhc2UsIGdldERhdGEsIGFkZERhdGEsIGFkZERhdGFBcnJheSB9IGZyb20gXCIuL2RiLmpzXCJcblxuZGVjbGFyZSBsZXQgbWFya2VkOiBhbnk7XG4vLyBsZXQgcG9zdHM6YW55O1xuLy8gbGV0IGtleUJhc2UgPSBcImRhbmRlbGlvbl9wb3N0c192MV9cIlxuLy8gbGV0IGtleTpzdHJpbmcgPSBcIlwiO1xuXG4vLyBpbnRlcmZhY2UgUG9zdFRpbWVzdGFtcCB7XG4vLyAgIHllYXI6IG51bWJlcixcbi8vICAgbW9udGg6IG51bWJlcixcbi8vICAgZGF5OiBudW1iZXIsXG4vLyAgIGhvdXI6IG51bWJlcixcbi8vICAgbWludXRlOiBudW1iZXIsXG4vLyAgIHNlY29uZDogbnVtYmVyLFxuLy8gfVxuXG5jbGFzcyBQb3N0IHtcbiAgcG9zdF90aW1lc3RhbXA6IERhdGU7XG4gIGF1dGhvcjogc3RyaW5nO1xuICBhdXRob3JfaWQ6IHN0cmluZztcbiAgdGV4dDogc3RyaW5nO1xuICBpbWFnZV9kYXRhOiBBcnJheUJ1ZmZlciB8IG51bGw7XG5cblxuICBpbXBvcnRlZEZyb206IFwidHdpdHRlclwiIHwgbnVsbDtcbiAgaW1wb3J0U291cmNlOiBhbnk7XG5cbiAgY29uc3RydWN0b3IoYXV0aG9yOiBzdHJpbmcsIGF1dGhvcl9pZDogc3RyaW5nLCB0ZXh0OiBzdHJpbmcsIHBvc3RfdGltZXN0YW1wOiBEYXRlLCBpbWFnZURhdGE6IEFycmF5QnVmZmVyIHwgbnVsbCA9IG51bGwsIGltcG9ydGVkRnJvbTogXCJ0d2l0dGVyXCIgfCBudWxsID0gbnVsbCwgaW1wb3J0U291cmNlOiBhbnkgPSBudWxsKSB7XG4gICAgdGhpcy5wb3N0X3RpbWVzdGFtcCA9IHBvc3RfdGltZXN0YW1wO1xuXG4gICAgdGhpcy5hdXRob3IgPSBhdXRob3I7XG4gICAgdGhpcy5hdXRob3JfaWQgPSBhdXRob3JfaWQ7XG4gICAgdGhpcy50ZXh0ID0gdGV4dDtcbiAgICB0aGlzLmltYWdlX2RhdGEgPSBpbWFnZURhdGE7XG5cbiAgICB0aGlzLmltcG9ydGVkRnJvbSA9IGltcG9ydGVkRnJvbTtcbiAgICB0aGlzLmltcG9ydFNvdXJjZSA9IGltcG9ydFNvdXJjZTtcbiAgfVxufVxuXG5cbmZ1bmN0aW9uIGluaXRNYXJrZG93bigpIHtcbiAgY29uc3QgcmVuZGVyZXIgPSBuZXcgbWFya2VkLlJlbmRlcmVyKCk7XG4gIHJlbmRlcmVyLmxpbmsgPSAoaHJlZjogYW55LCB0aXRsZTogc3RyaW5nLCB0ZXh0OiBzdHJpbmcpID0+IHtcbiAgICByZXR1cm4gYDxhIGhyZWY9XCIke2hyZWZ9XCIgdGFyZ2V0PVwiX2JsYW5rXCIke3RpdGxlID8gYCB0aXRsZT1cIiR7dGl0bGV9XCJgIDogJyd9PiR7dGV4dH08L2E+YDtcbiAgfTtcbiAgbWFya2VkLnNldE9wdGlvbnMoeyByZW5kZXJlcjogcmVuZGVyZXIgfSk7XG59XG5cbmZ1bmN0aW9uIHdhaXRNcyhkdXJhdGlvbk1zOiBudW1iZXIpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCBkdXJhdGlvbk1zKSk7XG59XG5cbmZ1bmN0aW9uIHV1aWR2NCgpIHtcbiAgcmV0dXJuIFwiMTAwMDAwMDAtMTAwMC00MDAwLTgwMDAtMTAwMDAwMDAwMDAwXCIucmVwbGFjZSgvWzAxOF0vZywgKGM6IGFueSkgPT5cbiAgICAoYyBeIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmV3IFVpbnQ4QXJyYXkoMSkpWzBdICYgMTUgPj4gYyAvIDQpLnRvU3RyaW5nKDE2KVxuICApO1xufVxuXG5sZXQgbG9nTGluZXM6IHN0cmluZ1tdID0gW107XG5sZXQgbG9nTGVuZ3RoID0gMTA7XG5mdW5jdGlvbiBsb2cobWVzc2FnZTogc3RyaW5nKSB7XG4gIGxvZ0xpbmVzLnB1c2goYCR7bmV3IERhdGUoKS50b0xvY2FsZVRpbWVTdHJpbmcoKX06ICR7bWVzc2FnZX1gKTtcbiAgaWYgKGxvZ0xpbmVzLmxlbmd0aCA+IDEwKSB7XG4gICAgbG9nTGluZXMgPSBsb2dMaW5lcy5zbGljZShsb2dMaW5lcy5sZW5ndGggLSBsb2dMZW5ndGgpO1xuICB9XG4gIGxldCBsb2cgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImxvZ1wiKTtcbiAgaWYgKCFsb2cpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgfVxuICBsb2cuaW5uZXJUZXh0ID0gbG9nTGluZXMuam9pbihcIlxcblwiKTtcbn1cblxuZnVuY3Rpb24gYXJyYXlCdWZmZXJUb0Jhc2U2NChidWZmZXI6IEFycmF5QnVmZmVyKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgYmxvYiA9IG5ldyBCbG9iKFtidWZmZXJdLCB7IHR5cGU6ICdhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0nIH0pO1xuICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XG5cbiAgICByZWFkZXIub25sb2FkZW5kID0gKCkgPT4ge1xuICAgICAgY29uc3QgZGF0YVVybCA9IHJlYWRlci5yZXN1bHQgYXMgc3RyaW5nO1xuICAgICAgaWYgKCFkYXRhVXJsKSB7XG4gICAgICAgIHJlc29sdmUobnVsbCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGJhc2U2NCA9IGRhdGFVcmwuc3BsaXQoJywnKVsxXTtcbiAgICAgIHJlc29sdmUoYmFzZTY0KTtcbiAgICB9O1xuXG4gICAgcmVhZGVyLm9uZXJyb3IgPSAoZXJyb3IpID0+IHtcbiAgICAgIHJlamVjdChlcnJvcik7XG4gICAgfTtcblxuICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGJsb2IpO1xuICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY3JlYXRlVGVzdERhdGEoKSB7XG4gIGxldCBwb3N0c1Rlc3REYXRhID0gYXdhaXQgKGF3YWl0IGZldGNoKFwiLi9wb3N0c1Rlc3REYXRhLmpzb25cIikpLmpzb24oKTtcblxuICByZXR1cm4gcG9zdHNUZXN0RGF0YTtcbn1cblxubGV0IHRpbWUgPSAwO1xuXG5mdW5jdGlvbiB0aW1lclN0YXJ0KCkge1xuICB0aW1lID0gcGVyZm9ybWFuY2Uubm93KCk7XG59XG5cbmZ1bmN0aW9uIHRpbWVyRGVsdGEoKSB7XG4gIHJldHVybiBwZXJmb3JtYW5jZS5ub3coKSAtIHRpbWU7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEZpeGVkVHdlZXRUZXh0KGVudHJ5OiBhbnkpIHtcblxuXG4gIGxldCBmdWxsVGV4dCA9IGVudHJ5LnR3ZWV0LmZ1bGxfdGV4dDtcblxuICBsZXQgbGlua01hcmtkb3duID0gXCJcIjtcbiAgZm9yIChjb25zdCB1cmwgb2YgZW50cnkudHdlZXQuZW50aXRpZXMudXJscykge1xuICAgIGxpbmtNYXJrZG93biA9IGBbJHt1cmwuZGlzcGxheV91cmx9XSgke3VybC5leHBhbmRlZF91cmx9KWA7XG4gICAgZnVsbFRleHQgPSBmdWxsVGV4dC5yZXBsYWNlKHVybC51cmwsIGxpbmtNYXJrZG93bik7XG4gIH1cblxuICByZXR1cm4gZnVsbFRleHRcbn1cblxuYXN5bmMgZnVuY3Rpb24gY3JlYXRlVGVzdERhdGEyKHVzZXJJRDogc3RyaW5nKSB7XG4gIGxvZyhcIkltcG9ydGluZyB0d2VldCBhcmNoaXZlXCIpXG4gIGxldCBwb3N0c1Rlc3REYXRhOiBhbnlbXSA9IFtdO1xuXG4gIGxldCByZXNwb25zZSA9IGF3YWl0IGZldGNoKFwiLi90d2VldHMuanNcIik7XG4gIGxldCB0d2VldHNUZXh0ID0gYXdhaXQgcmVzcG9uc2UudGV4dCgpO1xuICB0d2VldHNUZXh0ID0gdHdlZXRzVGV4dC5yZXBsYWNlKFwid2luZG93LllURC50d2VldHMucGFydDBcIiwgXCJ3aW5kb3cudHdlZXREYXRhXCIpO1xuXG4gIG5ldyBGdW5jdGlvbih0d2VldHNUZXh0KSgpO1xuXG5cbiAgLy8gbGV0IHR3ZWV0cyA9IEpTT04ucGFyc2UodHdlZXRKU09OKTtcbiAgbGV0IGNvdW50ID0gMDtcblxuICBmb3IgKGxldCBlbnRyeSBvZiAod2luZG93IGFzIGFueSkudHdlZXREYXRhKSB7XG4gICAgLy8gaWYgKGVudHJ5LnR3ZWV0Lmhhc093blByb3BlcnR5KFwiaW5fcmVwbHlfdG9fc2NyZWVuX25hbWVcIikgfHwgZW50cnkudHdlZXQucmV0d2VldGVkIHx8IGVudHJ5LnR3ZWV0LmZ1bGxfdGV4dC5zdGFydHNXaXRoKFwiUlRcIikpIHtcbiAgICAvLyAgIGNvbnRpbnVlO1xuICAgIC8vIH1cblxuICAgIGxldCBtZWRpYVVSTDogc3RyaW5nID0gZW50cnkudHdlZXQ/LmVudGl0aWVzPy5tZWRpYT8uWzBdPy5tZWRpYV91cmw7XG4gICAgbGV0IGlzSW1hZ2UgPSBmYWxzZTtcbiAgICBpZiAobWVkaWFVUkwpIHtcbiAgICAgIGlzSW1hZ2UgPSBtZWRpYVVSTC5pbmNsdWRlcygnanBnJyk7XG4gICAgfVxuXG4gICAgbGV0IGltYWdlRGF0YSA9IG51bGw7XG4gICAgaWYgKGlzSW1hZ2UpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGxldCByZXNwb25zZSA9IGF3YWl0IGZldGNoKG1lZGlhVVJMKTtcbiAgICAgICAgYXdhaXQgd2FpdE1zKDEwMCk7XG4gICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgIGltYWdlRGF0YSA9IGF3YWl0IHJlc3BvbnNlLmFycmF5QnVmZmVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc29sZS5sb2coaW1hZ2VEYXRhKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgICB9XG5cbiAgICB9XG5cbiAgICBsZXQgdGltZVN0YW1wID0gbmV3IERhdGUoZW50cnkudHdlZXQuY3JlYXRlZF9hdCk7XG4gICAgbGV0IHR3ZWV0VGV4dCA9IGF3YWl0IGdldEZpeGVkVHdlZXRUZXh0KGVudHJ5KTtcbiAgICBsZXQgbmV3UG9zdCA9IG5ldyBQb3N0KCdib2JieWRpZ2l0YWxlcycsIHVzZXJJRCwgdHdlZXRUZXh0LCB0aW1lU3RhbXAsIGltYWdlRGF0YSwgJ3R3aXR0ZXInLCBlbnRyeSk7XG5cbiAgICBwb3N0c1Rlc3REYXRhLnB1c2gobmV3UG9zdCk7XG5cbiAgICBjb3VudCsrO1xuICAgIGlmIChjb3VudCAlIDEwMCA9PT0gMCkge1xuICAgICAgbG9nKGBJbXBvcnRlZCAke2NvdW50fSBwb3N0cy4uLmApO1xuICAgICAgLy8gcmVuZGVyKHBvc3RzVGVzdERhdGEpO1xuICAgIH1cblxuICAgIC8vIGlmIChjb3VudCA9PSAxMDAtMSkge1xuICAgIC8vICAgYnJlYWs7XG4gICAgLy8gfVxuXG4gIH1cbiAgcmV0dXJuIHBvc3RzVGVzdERhdGE7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVRlc3REYXRhMyh1c2VySUQ6IHN0cmluZykge1xuICBsZXQgcG9zdHMgPSBhd2FpdCAoYXdhaXQgKGZldGNoKCcuL3Bvc3RzLmpzb24nKSkpLmpzb24oKTtcblxuICByZXR1cm4gcG9zdHM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlZ2lzdGVyU2VydmljZVdvcmtlcigpIHtcbiAgaWYgKCEoXCJzZXJ2aWNlV29ya2VyXCIgaW4gbmF2aWdhdG9yKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCByZWdpc3RyYXRpb25zID0gYXdhaXQgbmF2aWdhdG9yLnNlcnZpY2VXb3JrZXIuZ2V0UmVnaXN0cmF0aW9ucygpO1xuICBpZiAocmVnaXN0cmF0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgY29uc29sZS5sb2coXCJTZXJ2aWNlIHdvcmtlciBhbHJlYWR5IHJlZ2lzdGVyZWQuXCIpO1xuICAgIHJldHVybiByZWdpc3RyYXRpb25zWzBdO1xuICB9XG5cbiAgbmF2aWdhdG9yLnNlcnZpY2VXb3JrZXJcbiAgICAucmVnaXN0ZXIoXCIvc3cuanNcIilcbiAgICAudGhlbigocmVnaXN0cmF0aW9uKSA9PiB7XG4gICAgICBjb25zb2xlLmxvZyhcIlNlcnZpY2UgV29ya2VyIHJlZ2lzdGVyZWQgd2l0aCBzY29wZTpcIiwgcmVnaXN0cmF0aW9uLnNjb3BlKTtcbiAgICAgIHJldHVybiByZWdpc3RyYXRpb247XG4gICAgfSlcbiAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICBjb25zb2xlLmVycm9yKFwiU2VydmljZSBXb3JrZXIgcmVnaXN0cmF0aW9uIGZhaWxlZDpcIiwgZXJyb3IpO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBhZGRQb3N0KHVzZXJJRDogc3RyaW5nLCBwb3N0czogUG9zdFtdLCBwb3N0VGV4dDogc3RyaW5nKSB7XG4gIGlmICgodHlwZW9mIHBvc3RUZXh0ICE9PSBcInN0cmluZ1wiKSB8fCBwb3N0VGV4dC5sZW5ndGggPT09IDApIHtcbiAgICBsb2coXCJOb3QgcG9zdGluZyBhbiBlbXB0eSBzdHJpbmcuLi5cIilcbiAgICByZXR1cm47XG4gIH1cblxuICBsZXQgcG9zdCA9IG5ldyBQb3N0KGBib2JieWRpZ2l0YWxlc2AsIHVzZXJJRCwgcG9zdFRleHQsIG5ldyBEYXRlKCkpO1xuXG4gIHBvc3RzLnB1c2gocG9zdCk7XG4gIC8vIGxvY2FsU3RvcmFnZS5zZXRJdGVtKGtleSwgSlNPTi5zdHJpbmdpZnkocG9zdHMpKTtcbiAgYWRkRGF0YSh1c2VySUQsIHBvc3QpXG5cbiAgcmVuZGVyKHBvc3RzKTtcbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVJRCgpIHtcbiAgaWYgKHNlbGYuY3J5cHRvLmhhc093blByb3BlcnR5KFwicmFuZG9tVVVJRFwiKSkge1xuICAgIHJldHVybiBzZWxmLmNyeXB0by5yYW5kb21VVUlEKCk7XG4gIH1cblxuICByZXR1cm4gdXVpZHY0KCk7XG59XG5cbmZ1bmN0aW9uIGdldFVzZXJJRCgpIHtcbiAgbGV0IGlkID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJkYW5kZWxpb25faWRcIik7XG5cbiAgaWYgKCFpZCkge1xuICAgIGlkID0gZ2VuZXJhdGVJRCgpO1xuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFwiZGFuZGVsaW9uX2lkXCIsIGlkKTtcbiAgfVxuXG4gIHJldHVybiBpZDtcbn1cblxuZnVuY3Rpb24gY29ubmVjdFdlYnNvY2tldCh1c2VySUQ6IHN0cmluZykge1xuICBsZXQgd2Vic29ja2V0ID0gbmV3IFdlYlNvY2tldChgd3M6Ly8ke3dpbmRvdy5sb2NhdGlvbi5ob3N0bmFtZX06JHt3aW5kb3cubG9jYXRpb24ucG9ydH0vd3NgKTtcblxuICB3ZWJzb2NrZXQub25vcGVuID0gZnVuY3Rpb24gKGV2dCkge1xuICAgIGxvZyhcIldlYnNvY2tldDogQ09OTkVDVEVEXCIpO1xuICAgIHdlYnNvY2tldC5zZW5kKGB7XCJtZXNzYWdlVHlwZVwiOlwiY29ubmVjdFwiLCBcImlkXCI6IFwiJHt1c2VySUR9XCJ9YCk7XG4gIH07XG5cbiAgd2Vic29ja2V0Lm9uY2xvc2UgPSBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgbG9nKFwiV2Vic29ja2V0OiBESVNDT05ORUNURURcIik7XG4gIH07XG5cbiAgd2Vic29ja2V0Lm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChldnQpIHtcbiAgICBsb2coJ1dlYnNvY2tldDogUkVTUE9OU0U6ICcgKyBldnQuZGF0YSk7XG4gIH07XG5cbiAgd2Vic29ja2V0Lm9uZXJyb3IgPSBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgbG9nKCdXZWJzb2NrZXQ6IEVSUk9SOiAnICsgZXZ0KTtcbiAgfTtcblxuICByZXR1cm4gd2Vic29ja2V0O1xufVxuXG5mdW5jdGlvbiBzZXRGb250KGZvbnROYW1lOiBzdHJpbmcpIHtcblxuICBkb2N1bWVudC5ib2R5LnN0eWxlLmZvbnRGYW1pbHkgPSBmb250TmFtZTtcbiAgbGV0IHRleHRBcmVhID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3RleHRhcmVhX3Bvc3QnKTtcbiAgaWYgKCF0ZXh0QXJlYSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRleHRBcmVhLnN0eWxlLmZvbnRGYW1pbHkgPSBmb250TmFtZTtcbn1cblxuZnVuY3Rpb24gaW5pdE9mZmxpbmUoKSB7XG4gIC8vIEV2ZW50IGxpc3RlbmVyIGZvciBnb2luZyBvZmZsaW5lXG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdvZmZsaW5lJywgKCkgPT4geyBsb2coXCJvZmZsaW5lXCIpIH0pO1xuXG4gIC8vIEV2ZW50IGxpc3RlbmVyIGZvciBnb2luZyBvbmxpbmVcbiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ29ubGluZScsICgpID0+IHsgbG9nKFwib25saW5lXCIpIH0pO1xuXG4gIGxvZyhgT25saW5lIHN0YXR1czogJHtuYXZpZ2F0b3Iub25MaW5lID8gXCJvbmxpbmVcIiA6IFwib2ZmbGluZVwifWApXG5cbn1cblxuZnVuY3Rpb24gaW5pdEJ1dHRvbnModXNlcklEOiBzdHJpbmcsIHBvc3RzOiBQb3N0W10pIHtcbiAgbGV0IGZvbnQxQnV0dG9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJidXR0b25fZm9udDFcIikgYXMgSFRNTEJ1dHRvbkVsZW1lbnQ7XG4gIGxldCBmb250MkJ1dHRvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiYnV0dG9uX2ZvbnQyXCIpIGFzIEhUTUxCdXR0b25FbGVtZW50O1xuXG4gIGZvbnQxQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4geyBzZXRGb250KCdCb29rZXJseScpOyB9KTtcbiAgZm9udDJCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7IHNldEZvbnQoJ1ZpcmdpbCcpIH0pO1xuXG5cbiAgbGV0IHBvc3RCdXR0b24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImJ1dHRvbl9wb3N0XCIpIGFzIEhUTUxCdXR0b25FbGVtZW50O1xuICBsZXQgcG9zdFRleHQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInRleHRhcmVhX3Bvc3RcIikgYXMgSFRNTFRleHRBcmVhRWxlbWVudDtcblxuICBpZiAoIShwb3N0QnV0dG9uICYmIHBvc3RUZXh0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9XG5cbiAgcG9zdEJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKCkgPT4ge1xuICAgIGFkZFBvc3QodXNlcklELCBwb3N0cywgcG9zdFRleHQudmFsdWUpO1xuICAgIHBvc3RUZXh0LnZhbHVlID0gXCJcIjtcbiAgfSk7XG5cbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZFBvc3RzKHVzZXJJRDogc3RyaW5nKSB7XG5cbiAgdGltZXJTdGFydCgpO1xuICBsZXQgcG9zdHM6IGFueSA9IGF3YWl0IGdldERhdGEodXNlcklELCBuZXcgRGF0ZSgyMDIyLCA4KSwgbmV3IERhdGUoKSk7XG5cbiAgaWYgKHBvc3RzLmxlbmd0aCA+IDApIHtcbiAgICBsb2coYExvYWRlZCAke3Bvc3RzLmxlbmd0aH0gcG9zdHMgaW4gJHt0aW1lckRlbHRhKCkudG9GaXhlZCgyKX1tc2ApO1xuICAgIHJldHVybiBwb3N0cztcbiAgfVxuXG4gIHBvc3RzID0gYXdhaXQgY3JlYXRlVGVzdERhdGEyKHVzZXJJRCk7XG5cbiAgbG9nKFwiQWRkaW5nIHRlc3QgZGF0YS4uLlwiKTtcbiAgYWRkRGF0YUFycmF5KHVzZXJJRCwgcG9zdHMpO1xuICByZXR1cm4gYXdhaXQgZ2V0RGF0YSh1c2VySUQsIG5ldyBEYXRlKDIwMjIsIDgpLCBuZXcgRGF0ZSgpKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgbGV0IHBvc3RzOiBQb3N0W10gPSBbXTtcbiAgbGV0IHRpbWUgPSAwOyBgYFxuICBsZXQgZGVsdGEgPSAwO1xuXG4gIGxldCB1cmxQYXJhbXMgPSAobmV3IFVSTCh3aW5kb3cubG9jYXRpb24uaHJlZikpLnNlYXJjaFBhcmFtcztcblxuICBpZiAodXJsUGFyYW1zLmdldChcInN3XCIpID09PSBcInRydWVcIikge1xuICAgIGxldCByZWdpc3RyYXRpb24gPSBhd2FpdCByZWdpc3RlclNlcnZpY2VXb3JrZXIoKTtcbiAgfVxuXG4gIGxldCB1c2VySUQgPSBnZXRVc2VySUQoKTtcbiAgbG9nKGBZb3VyIHVzZXIgSUQgaXM6ICR7dXNlcklEfWApO1xuXG4gIGlmIChuYXZpZ2F0b3Iuc3RvcmFnZSAmJiBuYXZpZ2F0b3Iuc3RvcmFnZS5wZXJzaXN0ICYmICFuYXZpZ2F0b3Iuc3RvcmFnZS5wZXJzaXN0ZWQpIHtcbiAgICBjb25zdCBpc1BlcnNpc3RlZCA9IGF3YWl0IG5hdmlnYXRvci5zdG9yYWdlLnBlcnNpc3QoKTtcbiAgICBsb2coYFBlcnNpc3RlZCBzdG9yYWdlIGdyYW50ZWQ6ICR7aXNQZXJzaXN0ZWR9YCk7XG4gIH1cblxuICBsb2coYFBlcnNpc3RlZDogJHsoYXdhaXQgbmF2aWdhdG9yLnN0b3JhZ2UucGVyc2lzdGVkKCkpLnRvU3RyaW5nKCl9YCk7XG5cbiAgaW5pdE1hcmtkb3duKCk7XG5cbiAgLy8gbGV0IG1haW4gPSBhd2FpdCBmZXRjaChcIi9tYWluLmpzXCIpO1xuICAvLyBsZXQgY29kZSA9IGF3YWl0IG1haW4udGV4dCgpO1xuICAvLyAgIGNvbnNvbGUubG9nKGNvZGUpO1xuICAvLyAgIHJlZ2lzdHJhdGlvbi5hY3RpdmUucG9zdE1lc3NhZ2Uoe3R5cGU6XCJ1cGRhdGVNYWluXCIsIGNvZGU6Y29kZX0pO1xuXG4gIHBvc3RzID0gYXdhaXQgbG9hZFBvc3RzKHVzZXJJRCk7XG5cbiAgbGV0IHdlYnNvY2tldCA9IGNvbm5lY3RXZWJzb2NrZXQodXNlcklEKTtcbiAgaW5pdE9mZmxpbmUoKTtcbiAgaW5pdEJ1dHRvbnModXNlcklELCBwb3N0cyk7XG4gIC8vIGRlYnVnZ2VyO1xuXG4gIHRpbWVyU3RhcnQoKTtcbiAgcmVuZGVyKHBvc3RzKTtcbiAgbGV0IHJlbmRlclRpbWUgPSB0aW1lckRlbHRhKCk7XG5cbiAgbG9nKGByZW5kZXIgdG9vazogJHtyZW5kZXJUaW1lLnRvRml4ZWQoMil9bXNgKTtcblxuICBsb2coYG1lbW9yeSB1c2VkOiAkeygocGVyZm9ybWFuY2UgYXMgYW55KS5tZW1vcnkudXNlZEpTSGVhcFNpemUgLyAxMDI0IC8gMTAyNCkudG9GaXhlZCgyKX1NYmApXG59XG5cbmZ1bmN0aW9uIHJlbmRlcihwb3N0czogUG9zdFtdKSB7XG4gIGNvbnN0IGZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuICBsZXQgY29udGVudERpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiY29udGVudFwiKTtcbiAgaWYgKCFjb250ZW50RGl2KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH1cbiAgY29udGVudERpdi5pbm5lckhUTUwgPSBcIlwiO1xuICBsZXQgY291bnQgPSAwO1xuXG5cbiAgZm9yIChsZXQgaSA9IHBvc3RzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbGV0IHBvc3REYXRhID0gcG9zdHNbaV07XG5cbiAgICBsZXQgcG9zdCA9IHJlbmRlclBvc3QocG9zdERhdGEpO1xuXG4gICAgaWYgKHBvc3QpIHtcbiAgICAgIGZyYWdtZW50LmFwcGVuZENoaWxkKHBvc3QpO1xuICAgICAgY291bnQrKztcbiAgICB9XG4gICAgaWYgKGNvdW50ID4gMTAwKSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuXG4gIGlmICghY29udGVudERpdikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNvdWxkbid0IGdldCBjb250ZW50IGRpdiFcIik7XG4gIH1cblxuICBjb250ZW50RGl2LmFwcGVuZENoaWxkKGZyYWdtZW50KTtcblxufVxuXG5mdW5jdGlvbiByZW5kZXJQb3N0KHBvc3Q6IFBvc3QpIHtcbiAgaWYgKCEocG9zdC5oYXNPd25Qcm9wZXJ0eShcInRleHRcIikpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiUG9zdCBpcyBtYWxmb3JtZWQhXCIpO1xuICB9XG4gIGxldCBjb250YWluZXJEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICBsZXQgdGV4dERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gIGxldCB0aW1lc3RhbXBEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICBsZXQgaHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaHJcIik7XG5cblxuICB0ZXh0RGl2LmlubmVySFRNTCA9IG1hcmtlZC5wYXJzZShwb3N0LnRleHQpO1xuICAvLyB0ZXh0RGl2LmlubmVySFRNTCA9IERPTVB1cmlmeS5zYW5pdGl6ZShtYXJrZWQucGFyc2UocG9zdC50ZXh0KSk7XG5cbiAgdGltZXN0YW1wRGl2LmlubmVyVGV4dCA9IGAke3Bvc3QucG9zdF90aW1lc3RhbXAudG9EYXRlU3RyaW5nKCl9YDtcbiAgdGltZXN0YW1wRGl2LnRpdGxlID0gYCR7cG9zdC5wb3N0X3RpbWVzdGFtcC50b0xvY2FsZVRpbWVTdHJpbmcoKX0gwrcgJHtwb3N0LnBvc3RfdGltZXN0YW1wLnRvRGF0ZVN0cmluZygpfWBcbiAgY29udGFpbmVyRGl2LmFwcGVuZENoaWxkKGhyKTtcbiAgY29udGFpbmVyRGl2LmFwcGVuZENoaWxkKHRleHREaXYpO1xuXG4gIGlmICghKFwiaW1hZ2VfZGF0YVwiIGluIHBvc3QgJiYgcG9zdC5pbWFnZV9kYXRhKSkge1xuICAgIGNvbnRhaW5lckRpdi5hcHBlbmRDaGlsZCh0aW1lc3RhbXBEaXYpO1xuICAgIHJldHVybiBjb250YWluZXJEaXY7XG4gICAgLy8gcmV0dXJuIG51bGw7XG4gIH1cblxuICBsZXQgaW1hZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaW1nXCIpO1xuICBjb25zdCBibG9iID0gbmV3IEJsb2IoW3Bvc3QuaW1hZ2VfZGF0YSBhcyBBcnJheUJ1ZmZlcl0sIHsgdHlwZTogJ2ltYWdlL2pwZycgfSk7XG4gIGNvbnN0IHVybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XG4gIGltYWdlLm9ubG9hZCA9ICgpID0+IHtcbiAgICBVUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG4gIH07XG5cblxuICBpbWFnZS5zcmMgPSB1cmw7XG4gIC8vIGltYWdlLnNyYyA9IGltYWdlLnNyYyA9IFwiZGF0YTppbWFnZS9wbmc7YmFzZTY0LFwiICsgcG9zdC5pbWFnZTtcbiAgaW1hZ2UuY2xhc3NOYW1lID0gXCJwb3N0SW1hZ2VcIjtcblxuICBjb250YWluZXJEaXYuYXBwZW5kQ2hpbGQoaW1hZ2UpO1xuICBjb250YWluZXJEaXYuYXBwZW5kQ2hpbGQodGltZXN0YW1wRGl2KTtcblxuICByZXR1cm4gY29udGFpbmVyRGl2O1xufVxuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImxvYWRcIiwgbWFpbik7XG4iXX0=