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
================================================
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))
})