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.post_id = generateID(); 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBZ0IsT0FBTyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxTQUFTLENBQUE7QUFHdEUsaUJBQWlCO0FBQ2pCLHNDQUFzQztBQUN0Qyx1QkFBdUI7QUFFdkIsNEJBQTRCO0FBQzVCLGtCQUFrQjtBQUNsQixtQkFBbUI7QUFDbkIsaUJBQWlCO0FBQ2pCLGtCQUFrQjtBQUNsQixvQkFBb0I7QUFDcEIsb0JBQW9CO0FBQ3BCLElBQUk7QUFFSixNQUFNLElBQUk7SUFZUixZQUFZLE1BQWMsRUFBRSxTQUFpQixFQUFFLElBQVksRUFBRSxjQUFvQixFQUFFLFlBQWdDLElBQUksRUFBRSxlQUFpQyxJQUFJLEVBQUUsZUFBb0IsSUFBSTtRQUN0TCxJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztRQUNyQyxJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsRUFBRSxDQUFDO1FBRTVCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQzNCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDO1FBRTVCLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO0lBQ25DLENBQUM7Q0FDRjtBQUdELFNBQVMsWUFBWTtJQUNuQixNQUFNLFFBQVEsR0FBRyxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN2QyxRQUFRLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBUyxFQUFFLEtBQWEsRUFBRSxJQUFZLEVBQUUsRUFBRTtRQUN6RCxPQUFPLFlBQVksSUFBSSxvQkFBb0IsS0FBSyxDQUFDLENBQUMsQ0FBQyxXQUFX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O0lBQ2pFLEtBQUssQ0FBQyxTQUFTLEdBQUcsV0FBVyxDQUFDO0lBRTlCLFlBQVksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUV2QyxPQUFPLFlBQVksQ0FBQztBQUN0QixDQUFDO0FBRUQsTUFBTSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG9wZW5EYXRhYmFzZSwgZ2V0RGF0YSwgYWRkRGF0YSwgYWRkRGF0YUFycmF5IH0gZnJvbSBcIi4vZGIuanNcIlxuXG5kZWNsYXJlIGxldCBtYXJrZWQ6IGFueTtcbi8vIGxldCBwb3N0czphbnk7XG4vLyBsZXQga2V5QmFzZSA9IFwiZGFuZGVsaW9uX3Bvc3RzX3YxX1wiXG4vLyBsZXQga2V5OnN0cmluZyA9IFwiXCI7XG5cbi8vIGludGVyZmFjZSBQb3N0VGltZXN0YW1wIHtcbi8vICAgeWVhcjogbnVtYmVyLFxuLy8gICBtb250aDogbnVtYmVyLFxuLy8gICBkYXk6IG51bWJlcixcbi8vICAgaG91cjogbnVtYmVyLFxuLy8gICBtaW51dGU6IG51bWJlcixcbi8vICAgc2Vjb25kOiBudW1iZXIsXG4vLyB9XG5cbmNsYXNzIFBvc3Qge1xuICBwb3N0X3RpbWVzdGFtcDogRGF0ZTtcbiAgcG9zdF9pZDogc3RyaW5nO1xuICBhdXRob3I6IHN0cmluZztcbiAgYXV0aG9yX2lkOiBzdHJpbmc7XG4gIHRleHQ6IHN0cmluZztcbiAgaW1hZ2VfZGF0YTogQXJyYXlCdWZmZXIgfCBudWxsO1xuXG5cbiAgaW1wb3J0ZWRGcm9tOiBcInR3aXR0ZXJcIiB8IG51bGw7XG4gIGltcG9ydFNvdXJjZTogYW55O1xuXG4gIGNvbnN0cnVjdG9yKGF1dGhvcjogc3RyaW5nLCBhdXRob3JfaWQ6IHN0cmluZywgdGV4dDogc3RyaW5nLCBwb3N0X3RpbWVzdGFtcDogRGF0ZSwgaW1hZ2VEYXRhOiBBcnJheUJ1ZmZlciB8IG51bGwgPSBudWxsLCBpbXBvcnRlZEZyb206IFwidHdpdHRlclwiIHwgbnVsbCA9IG51bGwsIGltcG9ydFNvdXJjZTogYW55ID0gbnVsbCkge1xuICAgIHRoaXMucG9zdF90aW1lc3RhbXAgPSBwb3N0X3RpbWVzdGFtcDtcbiAgICB0aGlzLnBvc3RfaWQgPSBnZW5lcmF0ZUlEKCk7XG5cbiAgICB0aGlzLmF1dGhvciA9IGF1dGhvcjtcbiAgICB0aGlzLmF1dGhvcl9pZCA9IGF1dGhvcl9pZDtcbiAgICB0aGlzLnRleHQgPSB0ZXh0O1xuICAgIHRoaXMuaW1hZ2VfZGF0YSA9IGltYWdlRGF0YTtcblxuICAgIHRoaXMuaW1wb3J0ZWRGcm9tID0gaW1wb3J0ZWRGcm9tO1xuICAgIHRoaXMuaW1wb3J0U291cmNlID0gaW1wb3J0U291cmNlO1xuICB9XG59XG5cblxuZnVuY3Rpb24gaW5pdE1hcmtkb3duKCkge1xuICBjb25zdCByZW5kZXJlciA9IG5ldyBtYXJrZWQuUmVuZGVyZXIoKTtcbiAgcmVuZGVyZXIubGluayA9IChocmVmOiBhbnksIHRpdGxlOiBzdHJpbmcsIHRleHQ6IHN0cmluZykgPT4ge1xuICAgIHJldHVybiBgPGEgaHJlZj1cIiR7aHJlZn1cIiB0YXJnZXQ9XCJfYmxhbmtcIiR7dGl0bGUgPyBgIHRpdGxlPVwiJHt0aXRsZX1cImAgOiAnJ30+JHt0ZXh0fTwvYT5gO1xuICB9O1xuICBtYXJrZWQuc2V0T3B0aW9ucyh7IHJlbmRlcmVyOiByZW5kZXJlciB9KTtcbn1cblxuZnVuY3Rpb24gd2FpdE1zKGR1cmF0aW9uTXM6IG51bWJlcikge1xuICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIGR1cmF0aW9uTXMpKTtcbn1cblxuZnVuY3Rpb24gdXVpZHY0KCkge1xuICByZXR1cm4gXCIxMDAwMDAwMC0xMDAwLTQwMDAtODAwMC0xMDAwMDAwMDAwMDBcIi5yZXBsYWNlKC9bMDE4XS9nLCAoYzogYW55KSA9PlxuICAgIChjIF4gY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhuZXcgVWludDhBcnJheSgxKSlbMF0gJiAxNSA+PiBjIC8gNCkudG9TdHJpbmcoMTYpXG4gICk7XG59XG5cbmxldCBsb2dMaW5lczogc3RyaW5nW10gPSBbXTtcbmxldCBsb2dMZW5ndGggPSAxMDtcbmZ1bmN0aW9uIGxvZyhtZXNzYWdlOiBzdHJpbmcpIHtcbiAgbG9nTGluZXMucHVzaChgJHtuZXcgRGF0ZSgpLnRvTG9jYWxlVGltZVN0cmluZygpfTogJHttZXNzYWdlfWApO1xuICBpZiAobG9nTGluZXMubGVuZ3RoID4gMTApIHtcbiAgICBsb2dMaW5lcyA9IGxvZ0xpbmVzLnNsaWNlKGxvZ0xpbmVzLmxlbmd0aCAtIGxvZ0xlbmd0aCk7XG4gIH1cbiAgbGV0IGxvZyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwibG9nXCIpO1xuICBpZiAoIWxvZykge1xuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9XG4gIGxvZy5pbm5lclRleHQgPSBsb2dMaW5lcy5qb2luKFwiXFxuXCIpO1xufVxuXG5mdW5jdGlvbiBhcnJheUJ1ZmZlclRvQmFzZTY0KGJ1ZmZlcjogQXJyYXlCdWZmZXIpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW2J1ZmZlcl0sIHsgdHlwZTogJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScgfSk7XG4gICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcblxuICAgIHJlYWRlci5vbmxvYWRlbmQgPSAoKSA9PiB7XG4gICAgICBjb25zdCBkYXRhVXJsID0gcmVhZGVyLnJlc3VsdCBhcyBzdHJpbmc7XG4gICAgICBpZiAoIWRhdGFVcmwpIHtcbiAgICAgICAgcmVzb2x2ZShudWxsKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgYmFzZTY0ID0gZGF0YVVybC5zcGxpdCgnLCcpWzFdO1xuICAgICAgcmVzb2x2ZShiYXNlNjQpO1xuICAgIH07XG5cbiAgICByZWFkZXIub25lcnJvciA9IChlcnJvcikgPT4ge1xuICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICB9O1xuXG4gICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoYmxvYik7XG4gIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVUZXN0RGF0YSgpIHtcbiAgbGV0IHBvc3RzVGVzdERhdGEgPSBhd2FpdCAoYXdhaXQgZmV0Y2goXCIuL3Bvc3RzVGVzdERhdGEuanNvblwiKSkuanNvbigpO1xuXG4gIHJldHVybiBwb3N0c1Rlc3REYXRhO1xufVxuXG5sZXQgdGltZSA9IDA7XG5cbmZ1bmN0aW9uIHRpbWVyU3RhcnQoKSB7XG4gIHRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbn1cblxuZnVuY3Rpb24gdGltZXJEZWx0YSgpIHtcbiAgcmV0dXJuIHBlcmZvcm1hbmNlLm5vdygpIC0gdGltZTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0Rml4ZWRUd2VldFRleHQoZW50cnk6IGFueSkge1xuXG5cbiAgbGV0IGZ1bGxUZXh0ID0gZW50cnkudHdlZXQuZnVsbF90ZXh0O1xuXG4gIGxldCBsaW5rTWFya2Rvd24gPSBcIlwiO1xuICBmb3IgKGNvbnN0IHVybCBvZiBlbnRyeS50d2VldC5lbnRpdGllcy51cmxzKSB7XG4gICAgbGlua01hcmtkb3duID0gYFske3VybC5kaXNwbGF5X3VybH1dKCR7dXJsLmV4cGFuZGVkX3VybH0pYDtcbiAgICBmdWxsVGV4dCA9IGZ1bGxUZXh0LnJlcGxhY2UodXJsLnVybCwgbGlua01hcmtkb3duKTtcbiAgfVxuXG4gIHJldHVybiBmdWxsVGV4dFxufVxuXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVUZXN0RGF0YTIodXNlcklEOiBzdHJpbmcpIHtcbiAgbG9nKFwiSW1wb3J0aW5nIHR3ZWV0IGFyY2hpdmVcIilcbiAgbGV0IHBvc3RzVGVzdERhdGE6IGFueVtdID0gW107XG5cbiAgbGV0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goXCIuL3R3ZWV0cy5qc1wiKTtcbiAgbGV0IHR3ZWV0c1RleHQgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG4gIHR3ZWV0c1RleHQgPSB0d2VldHNUZXh0LnJlcGxhY2UoXCJ3aW5kb3cuWVRELnR3ZWV0cy5wYXJ0MFwiLCBcIndpbmRvdy50d2VldERhdGFcIik7XG5cbiAgbmV3IEZ1bmN0aW9uKHR3ZWV0c1RleHQpKCk7XG5cblxuICAvLyBsZXQgdHdlZXRzID0gSlNPTi5wYXJzZSh0d2VldEpTT04pO1xuICBsZXQgY291bnQgPSAwO1xuXG4gIGZvciAobGV0IGVudHJ5IG9mICh3aW5kb3cgYXMgYW55KS50d2VldERhdGEpIHtcbiAgICAvLyBpZiAoZW50cnkudHdlZXQuaGFzT3duUHJvcGVydHkoXCJpbl9yZXBseV90b19zY3JlZW5fbmFtZVwiKSB8fCBlbnRyeS50d2VldC5yZXR3ZWV0ZWQgfHwgZW50cnkudHdlZXQuZnVsbF90ZXh0LnN0YXJ0c1dpdGgoXCJSVFwiKSkge1xuICAgIC8vICAgY29udGludWU7XG4gICAgLy8gfVxuXG4gICAgbGV0IG1lZGlhVVJMOiBzdHJpbmcgPSBlbnRyeS50d2VldD8uZW50aXRpZXM/Lm1lZGlhPy5bMF0/Lm1lZGlhX3VybDtcbiAgICBsZXQgaXNJbWFnZSA9IGZhbHNlO1xuICAgIGlmIChtZWRpYVVSTCkge1xuICAgICAgaXNJbWFnZSA9IG1lZGlhVVJMLmluY2x1ZGVzKCdqcGcnKTtcbiAgICB9XG5cbiAgICBsZXQgaW1hZ2VEYXRhID0gbnVsbDtcbiAgICBpZiAoaXNJbWFnZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgbGV0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2gobWVkaWFVUkwpO1xuICAgICAgICBhd2FpdCB3YWl0TXMoMTAwKTtcbiAgICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgaW1hZ2VEYXRhID0gYXdhaXQgcmVzcG9uc2UuYXJyYXlCdWZmZXIoKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZyhpbWFnZURhdGEpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhlKTtcbiAgICAgIH1cblxuICAgIH1cblxuICAgIGxldCB0aW1lU3RhbXAgPSBuZXcgRGF0ZShlbnRyeS50d2VldC5jcmVhdGVkX2F0KTtcbiAgICBsZXQgdHdlZXRUZXh0ID0gYXdhaXQgZ2V0Rml4ZWRUd2VldFRleHQoZW50cnkpO1xuICAgIGxldCBuZXdQb3N0ID0gbmV3IFBvc3QoJ2JvYmJ5ZGlnaXRhbGVzJywgdXNlcklELCB0d2VldFRleHQsIHRpbWVTdGFtcCwgaW1hZ2VEYXRhLCAndHdpdHRlcicsIGVudHJ5KTtcblxuICAgIHBvc3RzVGVzdERhdGEucHVzaChuZXdQb3N0KTtcblxuICAgIGNvdW50Kys7XG4gICAgaWYgKGNvdW50ICUgMTAwID09PSAwKSB7XG4gICAgICBsb2coYEltcG9ydGVkICR7Y291bnR9IHBvc3RzLi4uYCk7XG4gICAgICAvLyByZW5kZXIocG9zdHNUZXN0RGF0YSk7XG4gICAgfVxuXG4gICAgLy8gaWYgKGNvdW50ID09IDEwMC0xKSB7XG4gICAgLy8gICBicmVhaztcbiAgICAvLyB9XG5cbiAgfVxuICByZXR1cm4gcG9zdHNUZXN0RGF0YTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY3JlYXRlVGVzdERhdGEzKHVzZXJJRDogc3RyaW5nKSB7XG4gIGxldCBwb3N0cyA9IGF3YWl0IChhd2FpdCAoZmV0Y2goJy4vcG9zdHMuanNvbicpKSkuanNvbigpO1xuXG4gIHJldHVybiBwb3N0cztcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVnaXN0ZXJTZXJ2aWNlV29ya2VyKCkge1xuICBpZiAoIShcInNlcnZpY2VXb3JrZXJcIiBpbiBuYXZpZ2F0b3IpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbGV0IHJlZ2lzdHJhdGlvbnMgPSBhd2FpdCBuYXZpZ2F0b3Iuc2VydmljZVdvcmtlci5nZXRSZWdpc3RyYXRpb25zKCk7XG4gIGlmIChyZWdpc3RyYXRpb25zLmxlbmd0aCA+IDApIHtcbiAgICBjb25zb2xlLmxvZyhcIlNlcnZpY2Ugd29ya2VyIGFscmVhZHkgcmVnaXN0ZXJlZC5cIik7XG4gICAgcmV0dXJuIHJlZ2lzdHJhdGlvbnNbMF07XG4gIH1cblxuICBuYXZpZ2F0b3Iuc2VydmljZVdvcmtlclxuICAgIC5yZWdpc3RlcihcIi9zdy5qc1wiKVxuICAgIC50aGVuKChyZWdpc3RyYXRpb24pID0+IHtcbiAgICAgIGNvbnNvbGUubG9nKFwiU2VydmljZSBXb3JrZXIgcmVnaXN0ZXJlZCB3aXRoIHNjb3BlOlwiLCByZWdpc3RyYXRpb24uc2NvcGUpO1xuICAgICAgcmV0dXJuIHJlZ2lzdHJhdGlvbjtcbiAgICB9KVxuICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJTZXJ2aWNlIFdvcmtlciByZWdpc3RyYXRpb24gZmFpbGVkOlwiLCBlcnJvcik7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGFkZFBvc3QodXNlcklEOiBzdHJpbmcsIHBvc3RzOiBQb3N0W10sIHBvc3RUZXh0OiBzdHJpbmcpIHtcbiAgaWYgKCh0eXBlb2YgcG9zdFRleHQgIT09IFwic3RyaW5nXCIpIHx8IHBvc3RUZXh0Lmxlbmd0aCA9PT0gMCkge1xuICAgIGxvZyhcIk5vdCBwb3N0aW5nIGFuIGVtcHR5IHN0cmluZy4uLlwiKVxuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCBwb3N0ID0gbmV3IFBvc3QoYGJvYmJ5ZGlnaXRhbGVzYCwgdXNlcklELCBwb3N0VGV4dCwgbmV3IERhdGUoKSk7XG5cbiAgcG9zdHMucHVzaChwb3N0KTtcbiAgLy8gbG9jYWxTdG9yYWdlLnNldEl0ZW0oa2V5LCBKU09OLnN0cmluZ2lmeShwb3N0cykpO1xuICBhZGREYXRhKHVzZXJJRCwgcG9zdClcblxuICByZW5kZXIocG9zdHMpO1xufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCkge1xuICBpZiAoc2VsZi5jcnlwdG8uaGFzT3duUHJvcGVydHkoXCJyYW5kb21VVUlEXCIpKSB7XG4gICAgcmV0dXJuIHNlbGYuY3J5cHRvLnJhbmRvbVVVSUQoKTtcbiAgfVxuXG4gIHJldHVybiB1dWlkdjQoKTtcbn1cblxuZnVuY3Rpb24gZ2V0VXNlcklEKCkge1xuICBsZXQgaWQgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbShcImRhbmRlbGlvbl9pZFwiKTtcblxuICBpZiAoIWlkKSB7XG4gICAgaWQgPSBnZW5lcmF0ZUlEKCk7XG4gICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oXCJkYW5kZWxpb25faWRcIiwgaWQpO1xuICB9XG5cbiAgcmV0dXJuIGlkO1xufVxuXG5mdW5jdGlvbiBjb25uZWN0V2Vic29ja2V0KHVzZXJJRDogc3RyaW5nKSB7XG4gIGxldCB3ZWJzb2NrZXQgPSBuZXcgV2ViU29ja2V0KGB3czovLyR7d2luZG93LmxvY2F0aW9uLmhvc3RuYW1lfToke3dpbmRvdy5sb2NhdGlvbi5wb3J0fS93c2ApO1xuXG4gIHdlYnNvY2tldC5vbm9wZW4gPSBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgbG9nKFwiV2Vic29ja2V0OiBDT05ORUNURURcIik7XG4gICAgd2Vic29ja2V0LnNlbmQoYHtcIm1lc3NhZ2VUeXBlXCI6XCJjb25uZWN0XCIsIFwiaWRcIjogXCIke3VzZXJJRH1cIn1gKTtcbiAgfTtcblxuICB3ZWJzb2NrZXQub25jbG9zZSA9IGZ1bmN0aW9uIChldnQpIHtcbiAgICBsb2coXCJXZWJzb2NrZXQ6IERJU0NPTk5FQ1RFRFwiKTtcbiAgfTtcblxuICB3ZWJzb2NrZXQub25tZXNzYWdlID0gZnVuY3Rpb24gKGV2dCkge1xuICAgIGxvZygnV2Vic29ja2V0OiBSRVNQT05TRTogJyArIGV2dC5kYXRhKTtcbiAgfTtcblxuICB3ZWJzb2NrZXQub25lcnJvciA9IGZ1bmN0aW9uIChldnQpIHtcbiAgICBsb2coJ1dlYnNvY2tldDogRVJST1I6ICcgKyBldnQpO1xuICB9O1xuXG4gIHJldHVybiB3ZWJzb2NrZXQ7XG59XG5cbmZ1bmN0aW9uIHNldEZvbnQoZm9udE5hbWU6IHN0cmluZykge1xuXG4gIGRvY3VtZW50LmJvZHkuc3R5bGUuZm9udEZhbWlseSA9IGZvbnROYW1lO1xuICBsZXQgdGV4dEFyZWEgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGV4dGFyZWFfcG9zdCcpO1xuICBpZiAoIXRleHRBcmVhKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdGV4dEFyZWEuc3R5bGUuZm9udEZhbWlseSA9IGZvbnROYW1lO1xufVxuXG5mdW5jdGlvbiBpbml0T2ZmbGluZSgpIHtcbiAgLy8gRXZlbnQgbGlzdGVuZXIgZm9yIGdvaW5nIG9mZmxpbmVcbiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ29mZmxpbmUnLCAoKSA9PiB7IGxvZyhcIm9mZmxpbmVcIikgfSk7XG5cbiAgLy8gRXZlbnQgbGlzdGVuZXIgZm9yIGdvaW5nIG9ubGluZVxuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignb25saW5lJywgKCkgPT4geyBsb2coXCJvbmxpbmVcIikgfSk7XG5cbiAgbG9nKGBPbmxpbmUgc3RhdHVzOiAke25hdmlnYXRvci5vbkxpbmUgPyBcIm9ubGluZVwiIDogXCJvZmZsaW5lXCJ9YClcblxufVxuXG5mdW5jdGlvbiBpbml0QnV0dG9ucyh1c2VySUQ6IHN0cmluZywgcG9zdHM6IFBvc3RbXSkge1xuICBsZXQgZm9udDFCdXR0b24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcImJ1dHRvbl9mb250MVwiKSBhcyBIVE1MQnV0dG9uRWxlbWVudDtcbiAgbGV0IGZvbnQyQnV0dG9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJidXR0b25fZm9udDJcIikgYXMgSFRNTEJ1dHRvbkVsZW1lbnQ7XG5cbiAgZm9udDFCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7IHNldEZvbnQoJ0Jvb2tlcmx5Jyk7IH0pO1xuICBmb250MkJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHsgc2V0Rm9udCgnVmlyZ2lsJykgfSk7XG5cblxuICBsZXQgcG9zdEJ1dHRvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiYnV0dG9uX3Bvc3RcIikgYXMgSFRNTEJ1dHRvbkVsZW1lbnQ7XG4gIGxldCBwb3N0VGV4dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwidGV4dGFyZWFfcG9zdFwiKSBhcyBIVE1MVGV4dEFyZWFFbGVtZW50O1xuXG4gIGlmICghKHBvc3RCdXR0b24gJiYgcG9zdFRleHQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH1cblxuICBwb3N0QnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoKSA9PiB7XG4gICAgYWRkUG9zdCh1c2VySUQsIHBvc3RzLCBwb3N0VGV4dC52YWx1ZSk7XG4gICAgcG9zdFRleHQudmFsdWUgPSBcIlwiO1xuICB9KTtcblxufVxuXG5hc3luYyBmdW5jdGlvbiBsb2FkUG9zdHModXNlcklEOiBzdHJpbmcpIHtcblxuICB0aW1lclN0YXJ0KCk7XG4gIGxldCBwb3N0czogYW55ID0gYXdhaXQgZ2V0RGF0YSh1c2VySUQsIG5ldyBEYXRlKDIwMjIsIDgpLCBuZXcgRGF0ZSgpKTtcblxuICBpZiAocG9zdHMubGVuZ3RoID4gMCkge1xuICAgIGxvZyhgTG9hZGVkICR7cG9zdHMubGVuZ3RofSBwb3N0cyBpbiAke3RpbWVyRGVsdGEoKS50b0ZpeGVkKDIpfW1zYCk7XG4gICAgcmV0dXJuIHBvc3RzO1xuICB9XG5cbiAgcG9zdHMgPSBhd2FpdCBjcmVhdGVUZXN0RGF0YTIodXNlcklEKTtcblxuICBsb2coXCJBZGRpbmcgdGVzdCBkYXRhLi4uXCIpO1xuICBhZGREYXRhQXJyYXkodXNlcklELCBwb3N0cyk7XG4gIHJldHVybiBhd2FpdCBnZXREYXRhKHVzZXJJRCwgbmV3IERhdGUoMjAyMiwgOCksIG5ldyBEYXRlKCkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBtYWluKCkge1xuICBsZXQgcG9zdHM6IFBvc3RbXSA9IFtdO1xuICBsZXQgdGltZSA9IDA7IGBgXG4gIGxldCBkZWx0YSA9IDA7XG5cbiAgbGV0IHVybFBhcmFtcyA9IChuZXcgVVJMKHdpbmRvdy5sb2NhdGlvbi5ocmVmKSkuc2VhcmNoUGFyYW1zO1xuXG4gIGlmICh1cmxQYXJhbXMuZ2V0KFwic3dcIikgPT09IFwidHJ1ZVwiKSB7XG4gICAgbGV0IHJlZ2lzdHJhdGlvbiA9IGF3YWl0IHJlZ2lzdGVyU2VydmljZVdvcmtlcigpO1xuICB9XG5cbiAgbGV0IHVzZXJJRCA9IGdldFVzZXJJRCgpO1xuICBsb2coYFlvdXIgdXNlciBJRCBpczogJHt1c2VySUR9YCk7XG5cbiAgaWYgKG5hdmlnYXRvci5zdG9yYWdlICYmIG5hdmlnYXRvci5zdG9yYWdlLnBlcnNpc3QgJiYgIW5hdmlnYXRvci5zdG9yYWdlLnBlcnNpc3RlZCkge1xuICAgIGNvbnN0IGlzUGVyc2lzdGVkID0gYXdhaXQgbmF2aWdhdG9yLnN0b3JhZ2UucGVyc2lzdCgpO1xuICAgIGxvZyhgUGVyc2lzdGVkIHN0b3JhZ2UgZ3JhbnRlZDogJHtpc1BlcnNpc3RlZH1gKTtcbiAgfVxuXG4gIGxvZyhgUGVyc2lzdGVkOiAkeyhhd2FpdCBuYXZpZ2F0b3Iuc3RvcmFnZS5wZXJzaXN0ZWQoKSkudG9TdHJpbmcoKX1gKTtcblxuICBpbml0TWFya2Rvd24oKTtcblxuICAvLyBsZXQgbWFpbiA9IGF3YWl0IGZldGNoKFwiL21haW4uanNcIik7XG4gIC8vIGxldCBjb2RlID0gYXdhaXQgbWFpbi50ZXh0KCk7XG4gIC8vICAgY29uc29sZS5sb2coY29kZSk7XG4gIC8vICAgcmVnaXN0cmF0aW9uLmFjdGl2ZS5wb3N0TWVzc2FnZSh7dHlwZTpcInVwZGF0ZU1haW5cIiwgY29kZTpjb2RlfSk7XG5cbiAgcG9zdHMgPSBhd2FpdCBsb2FkUG9zdHModXNlcklEKTtcblxuICBsZXQgd2Vic29ja2V0ID0gY29ubmVjdFdlYnNvY2tldCh1c2VySUQpO1xuICBpbml0T2ZmbGluZSgpO1xuICBpbml0QnV0dG9ucyh1c2VySUQsIHBvc3RzKTtcbiAgLy8gZGVidWdnZXI7XG5cbiAgdGltZXJTdGFydCgpO1xuICByZW5kZXIocG9zdHMpO1xuICBsZXQgcmVuZGVyVGltZSA9IHRpbWVyRGVsdGEoKTtcblxuICBsb2coYHJlbmRlciB0b29rOiAke3JlbmRlclRpbWUudG9GaXhlZCgyKX1tc2ApO1xuXG4gIGxvZyhgbWVtb3J5IHVzZWQ6ICR7KChwZXJmb3JtYW5jZSBhcyBhbnkpLm1lbW9yeS51c2VkSlNIZWFwU2l6ZSAvIDEwMjQgLyAxMDI0KS50b0ZpeGVkKDIpfU1iYClcbn1cblxuZnVuY3Rpb24gcmVuZGVyKHBvc3RzOiBQb3N0W10pIHtcbiAgY29uc3QgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG4gIGxldCBjb250ZW50RGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJjb250ZW50XCIpO1xuICBpZiAoIWNvbnRlbnREaXYpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgfVxuICBjb250ZW50RGl2LmlubmVySFRNTCA9IFwiXCI7XG4gIGxldCBjb3VudCA9IDA7XG5cblxuICBmb3IgKGxldCBpID0gcG9zdHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBsZXQgcG9zdERhdGEgPSBwb3N0c1tpXTtcblxuICAgIGxldCBwb3N0ID0gcmVuZGVyUG9zdChwb3N0RGF0YSk7XG5cbiAgICBpZiAocG9zdCkge1xuICAgICAgZnJhZ21lbnQuYXBwZW5kQ2hpbGQocG9zdCk7XG4gICAgICBjb3VudCsrO1xuICAgIH1cbiAgICBpZiAoY291bnQgPiAxMDApIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG5cbiAgaWYgKCFjb250ZW50RGl2KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGRuJ3QgZ2V0IGNvbnRlbnQgZGl2IVwiKTtcbiAgfVxuXG4gIGNvbnRlbnREaXYuYXBwZW5kQ2hpbGQoZnJhZ21lbnQpO1xuXG59XG5cbmZ1bmN0aW9uIHJlbmRlclBvc3QocG9zdDogUG9zdCkge1xuICBpZiAoIShwb3N0Lmhhc093blByb3BlcnR5KFwidGV4dFwiKSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJQb3N0IGlzIG1hbGZvcm1lZCFcIik7XG4gIH1cbiAgbGV0IGNvbnRhaW5lckRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gIGxldCB0ZXh0RGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgbGV0IHRpbWVzdGFtcERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gIGxldCBociA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJoclwiKTtcblxuXG4gIHRleHREaXYuaW5uZXJIVE1MID0gbWFya2VkLnBhcnNlKHBvc3QudGV4dCk7XG4gIC8vIHRleHREaXYuaW5uZXJIVE1MID0gRE9NUHVyaWZ5LnNhbml0aXplKG1hcmtlZC5wYXJzZShwb3N0LnRleHQpKTtcblxuICB0aW1lc3RhbXBEaXYuaW5uZXJUZXh0ID0gYCR7cG9zdC5wb3N0X3RpbWVzdGFtcC50b0RhdGVTdHJpbmcoKX1gO1xuICB0aW1lc3RhbXBEaXYudGl0bGUgPSBgJHtwb3N0LnBvc3RfdGltZXN0YW1wLnRvTG9jYWxlVGltZVN0cmluZygpfSDCtyAke3Bvc3QucG9zdF90aW1lc3RhbXAudG9EYXRlU3RyaW5nKCl9YFxuICBjb250YWluZXJEaXYuYXBwZW5kQ2hpbGQoaHIpO1xuICBjb250YWluZXJEaXYuYXBwZW5kQ2hpbGQodGV4dERpdik7XG5cbiAgaWYgKCEoXCJpbWFnZV9kYXRhXCIgaW4gcG9zdCAmJiBwb3N0LmltYWdlX2RhdGEpKSB7XG4gICAgY29udGFpbmVyRGl2LmFwcGVuZENoaWxkKHRpbWVzdGFtcERpdik7XG4gICAgcmV0dXJuIGNvbnRhaW5lckRpdjtcbiAgICAvLyByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGxldCBpbWFnZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJpbWdcIik7XG4gIGNvbnN0IGJsb2IgPSBuZXcgQmxvYihbcG9zdC5pbWFnZV9kYXRhIGFzIEFycmF5QnVmZmVyXSwgeyB0eXBlOiAnaW1hZ2UvanBnJyB9KTtcbiAgY29uc3QgdXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcbiAgaW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgIFVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcbiAgfTtcblxuXG4gIGltYWdlLnNyYyA9IHVybDtcbiAgLy8gaW1hZ2Uuc3JjID0gaW1hZ2Uuc3JjID0gXCJkYXRhOmltYWdlL3BuZztiYXNlNjQsXCIgKyBwb3N0LmltYWdlO1xuICBpbWFnZS5jbGFzc05hbWUgPSBcInBvc3RJbWFnZVwiO1xuXG4gIGNvbnRhaW5lckRpdi5hcHBlbmRDaGlsZChpbWFnZSk7XG4gIGNvbnRhaW5lckRpdi5hcHBlbmRDaGlsZCh0aW1lc3RhbXBEaXYpO1xuXG4gIHJldHVybiBjb250YWluZXJEaXY7XG59XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwibG9hZFwiLCBtYWluKTtcbiJdfQ==