// --- Constants --- const app = document.querySelector("#app"); const delay = ms => new Promise(res => setTimeout(res, ms)); // --- Data Definitions --- const links = [ { name: "blog", url: "https://blog.rikki.moe", desc: "Who am i and what do i do." }, { name: "git", url: "https://git.rikki.moe", desc: "My personal git server." }, { name: "github", url: "https://github.com/rikkix", desc: "My github page with my projects. Follow me there ;)" }, { name: "matrix-chat", url: "https://chat.mtf.moe", desc: "My personal matrix chat server." } ]; const commands = [ ...links, { name: "email", desc: "Get my email address." }, { name: "help", desc: "Show the list of commands." }, { name: "clear", desc: "Clear the terminal." } ]; // --- Event Listeners --- app.addEventListener("keypress", async function (event) { if (event.key === "Enter") { await delay(150); await executeInput(); } }); app.addEventListener("click", function () { const input = document.querySelector("input"); input.focus(); }); // --- Terminal Initialization --- async function open_terminal() { createText("Welcome to Rikki's terminal"); await delay(700); createText("Type 'help' to see the list of commands."); await delay(500); new_line(); executeInput("help"); } // --- Utility Functions --- function scrollToBottom() { const scrollHeight = app.scrollHeight; app.scrollTop = scrollHeight; } function new_line() { const p = document.createElement("p"); const span1 = document.createElement("span"); p.setAttribute("class", "path"); p.textContent = "guest@rikki"; span1.textContent = " ~"; p.appendChild(span1); app.appendChild(p); const div = document.createElement("div"); div.setAttribute("class", "type"); const i = document.createElement("i"); i.setAttribute("class", "fas fa-angle-right icone"); const input = document.createElement("input"); div.appendChild(i); div.appendChild(input); app.appendChild(div); input.focus(); } function removeInput() { const div = document.querySelector(".type"); app.removeChild(div); } // --- Command Handlers --- async function executeInput(command) { var value = command ? command : document.querySelector("input").value; removeInput(); value = value.trim(); const args = value.split(" "); const commandName = args[0]; await showOutput(commandName, args); new_line(); } async function showOutput(command, args) { switch (command) { case "help": trueValue(command); help(); break; case "clear": clearTerminal(); break; case "su": case "sudo": trueValue(command); createText("You are now root."); await delay(400); createText("Just kidding, you are still guest."); break; case "email": trueValue(command); createText("Getting email address..."); // record the time taken to get the email address const startTime = performance.now(); const email = await getEmailAddress(); const endTime = performance.now(); const timeTaken = endTime - startTime; createText(`The email address is: ${email} (${timeTaken.toFixed(2)}ms)`); break; default: handleLinkCommands(command); break; } } function help() { commands.forEach(command => printCommand(command.name, command.desc)); } function clearTerminal() { document.querySelectorAll("p, section").forEach(e => e.parentNode.removeChild(e)); } async function handleLinkCommands(command) { for (let link of links) { if (command === link.name) { trueValue(command); createText(`Opening ${link.name} (${link.url})`); scrollToBottom(); await delay(400); window.open(link.url, "_blank"); return; } } falseValue(command); createErrorText(`command not found: ${command}`); } // --- Command Output Helpers --- function trueValue(value) { const div = document.createElement("section"); div.setAttribute("class", "type2"); const i = document.createElement("i"); i.setAttribute("class", "fas fa-angle-right icone"); const mensagem = document.createElement("h2"); mensagem.setAttribute("class", "sucess"); mensagem.textContent = `${value}`; div.appendChild(i); div.appendChild(mensagem); app.appendChild(div); } function falseValue(value) { const div = document.createElement("section"); div.setAttribute("class", "type2"); const i = document.createElement("i"); i.setAttribute("class", "fas fa-angle-right icone error"); const mensagem = document.createElement("h2"); mensagem.setAttribute("class", "error"); mensagem.textContent = `${value}`; div.appendChild(i); div.appendChild(mensagem); app.appendChild(div); } function createText(text) { const p = document.createElement("p"); p.innerHTML = text; app.appendChild(p); } function printCommand(command, desc) { const p = document.createElement("p"); p.setAttribute("class", "code"); const cmdEle = document.createElement("a"); cmdEle.setAttribute("class", "command"); cmdEle.innerText = command; cmdEle.addEventListener("click", async function () { await delay(150); await executeInput(command); }); cmdEle.style.cursor = "pointer"; const descEle = document.createElement("span"); descEle.setAttribute("class", "text"); descEle.innerText = desc; p.appendChild(cmdEle); p.appendChild(document.createElement("br")); p.appendChild(descEle); app.appendChild(p); } function createErrorText(text) { const p = document.createElement("p"); p.innerText = text; app.appendChild(p); } // --- Email Fetching --- async function getEmailAddress() { const partHash = "2f5ab71af6dfd2f3c5444a2d690fbbb880ee87f9"; const remainingPart = "rikki.moe"; const chars = 'abcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()'; for (let i = 0; i < chars.length; i++) { for (let j = 0; j < chars.length; j++) { const part = chars[i] + chars[j]; const hash = await String2Hash(part); if (hash === partHash) { return part + remainingPart; } } } return null; } async function String2Hash(username) { const encoder = new TextEncoder(); const data = encoder.encode(username); const hashBuffer = await crypto.subtle.digest('SHA-1', data); return Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join(''); } // --- Terminal Start --- open_terminal();