Repository: lucaceriani/ooo Branch: main Commit: 86bbc4b6b134 Files: 6 Total size: 15.0 KB Directory structure: gitextract_tuebg16q/ ├── README.md ├── public/ │ ├── index.html │ ├── index.js │ ├── ooo.js │ └── style.css └── worker.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ # ooo The ultimate url lengthner ================================================ FILE: public/index.html ================================================ ooooooooooooooooooooooo.ooo | URL Lengthner

Looooooooooooooooooooooonger

================================================ FILE: public/index.js ================================================ const input = document.getElementById("input-url"); const output = document.getElementById("output-url"); const oooBtn = document.getElementById("ooo-button"); const copyBtn = document.getElementById("copy-button"); // init input.addEventListener("keydown", e => e.code == "Enter" ? oooify() : null) // mouse enter listener let oooBtnInt; oooBtn.addEventListener("mouseenter", () => oooBtnInt = setInterval(() => { console.log("a"); if (oooBtn.innerText == "oOo") oooBtn.innerText = "OoO"; else oooBtn.innerText = "oOo"; }, 200)); oooBtn.addEventListener("mouseleave", () => { clearInterval(oooBtnInt); // oooBtn.innerText = "oOo"; }); function oooify() { if (window.inBlinking) return try { new URL(input.value) } catch (e) { window.inBlinking = true input.style.opacity = 1 input.disabled = true let oldValue = input.value input.value = "Invalid URL! Noooooooooooo D:" let times = 0 let i = setInterval(async () => { if (parseInt(input.style.opacity) == 1) input.style.opacity = 0.2; else input.style.opacity = 1; if (++times == 6) { clearInterval(i) input.value = oldValue input.disabled = false input.focus() inBlinking = false } }, 150) return } const domain = location.host; let url = new OOO().encodeUrl(input.value.trim()); url = `${location.protocol}//${domain}/${url}`; // show the output div document.getElementById("output-div").style.display = "block"; output.innerHTML = url; output.setAttribute("href", url); input.value = ""; } function copy() { const el = document.createElement('textarea'); el.value = output.innerHTML; document.body.appendChild(el); el.select(); document.execCommand('copy'); document.body.removeChild(el); copyBtn.parentNode.setAttribute("data-showme", ""); setTimeout(() => copyBtn.parentNode.removeAttribute("data-showme"), 1000); }; ================================================ FILE: public/ooo.js ================================================ class OOO { enc = ["o", "ο", "о", "ᴏ"] // 006f 03bf 043e 1d0f dec = { "o": "0", "ο": "1", "о": "2", "ᴏ": "3" } ver = { "oooo": true } currVer = "oooo" removeAndCheckVersion(ooo) { if (this.ver[ooo.substring(0, 4)]) { return ooo.substring(4) } else { return null } } addVersion(ooo) { return this.currVer + ooo } encodeUrl(url) { // get utf8 array let unversioned = this.toUTF8Array(url) // convert to string with base 4 // padstart very important! otherwise missing leading 0s .map(n => n.toString(4).padStart(4, "0")) // convert to array of characters .join("").split("") // map to the o's .map(x => this.enc[parseInt(x)]) // join into single string .join("") return this.addVersion(unversioned) } decodeUrl(ooo) { ooo = this.removeAndCheckVersion(ooo) if (ooo === null) return // get the base 4 string representation of the url let b4str = ooo.split("").map(x => this.dec[x]).join("") let utf8arr = [] // parse 4 characters at a time (255 in b10 = 3333 in b4) // remember adding leading 0s padding for (let i = 0; i < b4str.length; i += 4) utf8arr.push(parseInt(b4str.substring(i, i + 4), 4)) return this.Utf8ArrayToStr(utf8arr) } // from https://gist.github.com/joni/3760795 toUTF8Array(str) { var utf8 = []; for (var i = 0; i < str.length; i++) { var charcode = str.charCodeAt(i); if (charcode < 0x80) utf8.push(charcode); else if (charcode < 0x800) { utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f)); } else if (charcode < 0xd800 || charcode >= 0xe000) { utf8.push(0xe0 | (charcode >> 12), 0x80 | ((charcode >> 6) & 0x3f), 0x80 | (charcode & 0x3f)); } // surrogate pair else { i++; charcode = ((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff) utf8.push(0xf0 | (charcode >> 18), 0x80 | ((charcode >> 12) & 0x3f), 0x80 | ((charcode >> 6) & 0x3f), 0x80 | (charcode & 0x3f)); } } return utf8; } // from https://gist.github.com/wumingdan/759564f6cb887a55bceb Utf8ArrayToStr(array) { var out, i, len, c; var char2, char3; out = ""; len = array.length; i = 0; while (i < len) { c = array[i++]; switch (c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 0xxxxxxx out += String.fromCharCode(c); break; case 12: case 13: // 110x xxxx 10xx xxxx char2 = array[i++]; out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx char2 = array[i++]; char3 = array[i++]; out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; } } return out; } } ================================================ FILE: public/style.css ================================================ :root { --bright: #ffde03; --light: #fff3a8; --dark: #100700; --fs: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; --br: 5px; } * { box-sizing: border-box; } .container { margin-left: auto; margin-right: auto; width: 100%; max-width: 1200px; padding: 1em; } .d-flex { display: flex !important; } .input-url { width: 100%; margin-right: 1em; display: inline-block; padding: 0.6em 0.8em; } a { text-decoration: underline; color: inherit; } footer { text-align: center; margin: 1.5em 0; font-size: 80%; } html { overflow-x: hidden; } body { overflow-x: hidden; font-weight: 300; background-color: var(--bright); font-family: var(--fs); } /* footer sticky */ body { display: flex; min-height: 100vh; flex-direction: column; } div.container { flex: 1; } /* end footer */ h1 { font-weight: 800; font-size: 4em; } h2 { font-size: 1.5em; font-weight: 800; } input, input:focus, input:focus-visible, .form-control, button { outline: none; font-family: var(--fs); background-color: var(--light); border: 1px var(--dark); border-radius: var(--br); font-size: 1.2em; } ::placeholder { color: rgba(0, 0, 0, 0.5); } .form-control { /* ovverride also :focus and :active */ background-color: var(--light) !important; box-shadow: none !important; font-size: 1.4em; padding: 1em !important; } button { border-radius: var(--br); background-color: var(--dark); color: var(--light); margin: 1px; cursor: pointer; transition: 0.1s ease-in-out all; } button:hover { box-shadow: 2px 2px 0px 0px rgba(0, 0, 0, 0.22); transform: translate(-2px, -2px); } #ooo-button { font-weight: 800; width: 4em; } #copy-button { font-weight: 800; padding: 0.5em; margin-top: 2em; } #output-div { margin-top: 3em; } /* Tooltip container */ .tooltip { position: relative; display: inline-block; } /* Tooltip text */ .tooltip .tooltip-text { visibility: hidden; width: 120px; background-color: rgba(0, 0, 0, 0.8); color: #fff; text-align: center; padding: 1em 0.5em; border-radius: 6px; position: absolute; z-index: 1; top: 0; left: 50%; transform: translate(-50%, -50%); } /* Show the tooltip text when you mouse over the tooltip container */ .tooltip[data-showme] .tooltip-text { visibility: visible; } .tooltip .tooltip-text::after { content: " "; position: absolute; top: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: rgba(0, 0, 0, 0.8) transparent transparent transparent; } ================================================ FILE: worker.js ================================================ /** * V1 of OOO - cloudflare worker to redirect traffic to correct url */ class OOO { enc = ["o", "ο", "о", "ᴏ"] // 006f 03bf 043e 1d0f dec = { "o": "0", "ο": "1", "о": "2", "ᴏ": "3" } ver = { "oooo": true } currVer = "oooo" removeAndCheckVersion(ooo) { if (this.ver[ooo.substring(0, 4)]) { return ooo.substring(4) } else { return null } } addVersion(ooo) { return this.currVer + ooo } encodeUrl(url) { // get utf8 array let unversioned = this.toUTF8Array(url) // convert to string with base 4 // padstart very important! otherwise missing leading 0s .map(n => n.toString(4).padStart(4, "0")) // convert to array of characters .join("").split("") // map to the o's .map(x => this.enc[parseInt(x)]) // join into single string .join("") return this.addVersion(unversioned) } decodeUrl(ooo) { ooo = this.removeAndCheckVersion(ooo) if (ooo === null) return // get the base 4 string representation of the url let b4str = ooo.split("").map(x => this.dec[x]).join("") let utf8arr = [] // parse 4 characters at a time (255 in b10 = 3333 in b4) // remember adding leading 0s padding for (let i = 0; i < b4str.length; i += 4) utf8arr.push(parseInt(b4str.substring(i, i + 4), 4)) return this.Utf8ArrayToStr(utf8arr) } // from https://gist.github.com/joni/3760795 toUTF8Array(str) { var utf8 = []; for (var i = 0; i < str.length; i++) { var charcode = str.charCodeAt(i); if (charcode < 0x80) utf8.push(charcode); else if (charcode < 0x800) { utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f)); } else if (charcode < 0xd800 || charcode >= 0xe000) { utf8.push(0xe0 | (charcode >> 12), 0x80 | ((charcode >> 6) & 0x3f), 0x80 | (charcode & 0x3f)); } // surrogate pair else { i++; charcode = ((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff) utf8.push(0xf0 | (charcode >> 18), 0x80 | ((charcode >> 12) & 0x3f), 0x80 | ((charcode >> 6) & 0x3f), 0x80 | (charcode & 0x3f)); } } return utf8; } // from https://gist.github.com/wumingdan/759564f6cb887a55bceb Utf8ArrayToStr(array) { var out, i, len, c; var char2, char3; out = ""; len = array.length; i = 0; while (i < len) { c = array[i++]; switch (c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 0xxxxxxx out += String.fromCharCode(c); break; case 12: case 13: // 110x xxxx 10xx xxxx char2 = array[i++]; out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx char2 = array[i++]; char3 = array[i++]; out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; } } return out; } } async function handleRequest(request) { let reqUrl = new URL(request.url) let redirectLocation = new OOO().decodeUrl(decodeURI(reqUrl.pathname.replace("/", ""))) let response; try { response = Response.redirect(redirectLocation, 302) } catch(e) { response = new Response(null, {status: 400}) } return response } addEventListener("fetch", async event => { event.respondWith(handleRequest(event.request)) })