This commit is contained in:
rift 2024-11-03 20:05:10 -06:00
parent 835cb237d7
commit fc414951d1
6 changed files with 4728 additions and 5425 deletions

View file

@ -31,8 +31,6 @@
"@mercuryworkshop/epoxy-transport": "2.1.13", "@mercuryworkshop/epoxy-transport": "2.1.13",
"@mercuryworkshop/libcurl-transport": "^1.3.10", "@mercuryworkshop/libcurl-transport": "^1.3.10",
"@playform/compress": "^0.1.4", "@playform/compress": "^0.1.4",
"@rubynetwork/rammerhead": "^1.3.5",
"@rubynetwork/rammerhead-browser": "^1.0.9",
"@titaniumnetwork-dev/ultraviolet": "^3.2.7", "@titaniumnetwork-dev/ultraviolet": "^3.2.7",
"@svelte-drama/suspense": "0.5.1", "@svelte-drama/suspense": "0.5.1",
"@types/node": "^22.7.5", "@types/node": "^22.7.5",

9640
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,19 +1,25 @@
:root { :root {
--background-primary: #191724; --background-primary: #191724;
--background-lighter: #16121f; --background-lighter: #16121f;
--navbar-color: #26233a; --navbar-color: #26233a;
--navbar-height: 60px; --navbar-height: 60px;
--navbar-text-color: #7967dd; --navbar-text-color: #7967dd;
--navbar-link-color: #e0def4; --navbar-link-color: #e0def4;
--navbar-link-hover-color: gray; --navbar-link-hover-color: gray;
--navbar-font: "Roboto"; --navbar-font: "Roboto";
--input-text-color: #e0def4; --input-text-color: #e0def4;
--input-placeholder-color: white; --input-placeholder-color: white;
--input-background-color: #1f1d2e; --input-background-color: #1f1d2e;
--input-border-color: #eb6f92; --input-border-color: #eb6f92;
--input-border-size: 1.3px; --input-border-size: 1.3px;
--navbar-logo-filter: none; --navbar-logo-filter: none;
--dropdown-option-hover-color: #312a49; --dropdown-option-hover-color: #312a49;
--tab-color: var(--black); --tab-color: var(--black);
--border-color: #16121f; --border-color: #16121f;
}
.roboto {
font-family: "Roboto", sans-serif;
font-weight: 200;
font-style: normal;
} }

View file

@ -1,43 +1,33 @@
import { createServer } from "node:http"; import { createServer } from "node:http";
import rammerhead from "@rubynetwork/rammerhead"; import {
import { FastifyServerFactory, FastifyServerFactoryHandler, RawServerDefault } from "fastify"; FastifyServerFactory,
FastifyServerFactoryHandler,
RawServerDefault,
} from "fastify";
import wisp from "wisp-server-node"; import wisp from "wisp-server-node";
import { LOG_LEVEL, WispOptions } from "wisp-server-node/dist/Types.js"; import { LOG_LEVEL, WispOptions } from "wisp-server-node/dist/Types.js";
import { parsedDoc } from "./config.js"; import { parsedDoc } from "./config.js";
const rh = rammerhead.createRammerhead({
logLevel: parsedDoc.server.server.logging ? "debug" : "disabled",
reverseProxy: parsedDoc.server.rammerhead.reverseproxy,
disableLocalStorageSync: parsedDoc.server.rammerhead.localstorage_sync ? false : true,
disableHttp2: parsedDoc.server.rammerhead.http2 ? false : true
});
const wispOptions: WispOptions = { const wispOptions: WispOptions = {
logLevel: parsedDoc.server.server.logging ? LOG_LEVEL.DEBUG : LOG_LEVEL.NONE, logLevel: parsedDoc.server.server.logging ? LOG_LEVEL.DEBUG : LOG_LEVEL.NONE,
pingInterval: 30 pingInterval: 30,
}; };
const serverFactory: FastifyServerFactory = ( const serverFactory: FastifyServerFactory = (
handler: FastifyServerFactoryHandler handler: FastifyServerFactoryHandler
): RawServerDefault => { ): RawServerDefault => {
const httpServer = createServer(); const httpServer = createServer();
httpServer.on("request", (req, res) => { httpServer.on("request", (req, res) => {
if (rammerhead.shouldRouteRh(req)) { handler(req, res);
rammerhead.routeRhRequest(rh, req, res); });
} else { httpServer.on("upgrade", (req, socket, head) => {
handler(req, res); if (parsedDoc.server.server.wisp) {
} if (req.url?.endsWith("/wisp/")) {
}); wisp.routeRequest(req, socket as any, head, wispOptions);
httpServer.on("upgrade", (req, socket, head) => { }
if (rammerhead.shouldRouteRh(req)) { }
rammerhead.routeRhUpgrade(rh, req, socket, head); });
} else if (parsedDoc.server.server.wisp) { return httpServer;
if (req.url?.endsWith("/wisp/")) {
wisp.routeRequest(req, socket as any, head, wispOptions);
}
}
});
return httpServer;
}; };
export { serverFactory }; export { serverFactory };

View file

@ -4,8 +4,8 @@ import Header from "@components/Header.astro";
import MobileNavigation from "@components/MobileNavigation.astro"; import MobileNavigation from "@components/MobileNavigation.astro";
import SettingsLoader from "@components/settings/Loader.astro"; import SettingsLoader from "@components/settings/Loader.astro";
interface Props { interface Props {
title: string; title: string;
noHeader?: string; noHeader?: string;
} }
const { title, noHeader } = Astro.props; const { title, noHeader } = Astro.props;
@ -17,7 +17,7 @@ const { title, noHeader } = Astro.props;
<SettingsLoader transition:persist /> <SettingsLoader transition:persist />
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="description" content="Astro description" /> <meta name="description" content="Astro description" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" id="favicon" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" id="favicon" />
<link <link
rel="stylesheet" rel="stylesheet"
@ -30,14 +30,20 @@ const { title, noHeader } = Astro.props;
href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap" href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap"
as="style" as="style"
crossorigin="anonymous" crossorigin="anonymous"
/> />
<link rel="preload" href="https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu4mxK.woff2" as="font" type="font/woff2" crossorigin="anonymous" /> <link
rel="preload"
href="https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu4mxK.woff2"
as="font"
type="font/woff2"
crossorigin="anonymous"
/>
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<title>{title}</title> <title>{title}</title>
<ViewTransitions /> <ViewTransitions />
</head> </head>
<body class="h-full bg-primary"> <body class="h-full bg-primary">
{!noHeader && <Header /> } {!noHeader && <Header />}
<div class="h-full z-10 w-full fixed"> <div class="h-full z-10 w-full fixed">
<slot /> <slot />
</div> </div>
@ -82,70 +88,67 @@ const { title, noHeader } = Astro.props;
}); });
</script> </script>
<style> <style>
#mobileNavMenu { #mobileNavMenu {
-webkit-transition-duration: 600ms; -webkit-transition-duration: 600ms;
transition-duration: 600ms; transition-duration: 600ms;
transform: translateX(100%); transform: translateX(100%);
} }
</style> </style>
<style is:global> <style is:global>
.roboto {
font-family: var(--font-family), Roboto;
}
/* Custom scrollbar because the default ones look like ASS */ /* Custom scrollbar because the default ones look like ASS */
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 0.5rem; width: 0.5rem;
height: 0.5rem; height: 0.5rem;
} }
::-webkit-scrollbar-track { ::-webkit-scrollbar-track {
background: var(--navbar-color); background: var(--navbar-color);
} }
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
background: var(--navbar-text-color); background: var(--navbar-text-color);
} }
::-webkit-scrollbar-thumb:hover { ::-webkit-scrollbar-thumb:hover {
background: var(--navbar-link-color); background: var(--navbar-link-color);
} }
::-moz-scrollbar { ::-moz-scrollbar {
width: 0.5rem; width: 0.5rem;
height: 0.5rem; height: 0.5rem;
} }
::-moz-scrollbar-track { ::-moz-scrollbar-track {
background: var(--navbar-color); background: var(--navbar-color);
} }
::-moz-scrollbar-thumb { ::-moz-scrollbar-thumb {
background: var(--navbar-text-color); background: var(--navbar-text-color);
} }
::-moz-scrollbar-thumb:hover { ::-moz-scrollbar-thumb:hover {
background: var(--navbar-link-color); background: var(--navbar-link-color);
} }
::-ms-scrollbar { ::-ms-scrollbar {
width: 0.5rem; width: 0.5rem;
height: 0.5rem; height: 0.5rem;
} }
::-ms-scrollbar-track { ::-ms-scrollbar-track {
background: var(--navbar-color); background: var(--navbar-color);
} }
::-ms-scrollbar-thumb { ::-ms-scrollbar-thumb {
background: var(--navbar-text-color); background: var(--navbar-text-color);
} }
::-ms-scrollbar-thumb:hover { ::-ms-scrollbar-thumb:hover {
background: var(--navbar-link-color); background: var(--navbar-link-color);
} }
::-o-scrollbar { ::-o-scrollbar {
width: 0.5rem; width: 0.5rem;
height: 0.5rem; height: 0.5rem;
} }
::-o-scrollbar-track { ::-o-scrollbar-track {
background: var(--navbar-color); background: var(--navbar-color);
} }
::-o-scrollbar-thumb { ::-o-scrollbar-thumb {
background: var(--navbar-text-color); background: var(--navbar-text-color);
} }
::-o-scrollbar-thumb:hover { ::-o-scrollbar-thumb:hover {
background: var(--navbar-link-color); background: var(--navbar-link-color);
} }
</style> </style>
</body> </body>
</html> </html>

View file

@ -3,8 +3,11 @@ import Logo from "@components/Logo.astro";
import Layout from "@layouts/Layout.astro"; import Layout from "@layouts/Layout.astro";
import { getLangFromUrl, useTranslations } from "../../i18n/utils"; import { getLangFromUrl, useTranslations } from "../../i18n/utils";
export function getStaticPaths() { export function getStaticPaths() {
const STATIC_PATHS = [{ params: { lang: "en_US" } }, { params: { lang: "jp" } }]; const STATIC_PATHS = [
return STATIC_PATHS; { params: { lang: "en_US" } },
{ params: { lang: "jp" } },
];
return STATIC_PATHS;
} }
export const prerender = true; export const prerender = true;
const lang = getLangFromUrl(Astro.url); const lang = getLangFromUrl(Astro.url);
@ -13,13 +16,19 @@ import { VERSION } from "astro:env/client";
--- ---
<Layout title="Nebula"> <Layout title="Nebula">
<div class="flex flex-wrap mt-16 justify-center content-center w-full bg-primary fixed inset-0 h-[calc(100%-4rem)] z-0 flex-col items-center"> <div
<div class="w-full flex flex-col justify-center items-center content-center h-2/4"> class="flex flex-wrap mt-16 justify-center content-center w-full bg-primary fixed inset-0 h-[calc(100%-4rem)] z-0 flex-col items-center"
>
<div
class="w-full flex flex-col justify-center items-center content-center h-2/4"
>
<div class="flex flex-row items-center mb-8"> <div class="flex flex-row items-center mb-8">
<div class="h-32 w-32 fill-navbar-text-color"> <div class="h-32 w-32 fill-navbar-text-color">
<Logo /> <Logo />
</div> </div>
<h1 class="font-roboto whitespace-nowrap font-bold text-navbar-text-color sm:visible text-5xl sm:text-7xl roboto"> <h1
class="font-roboto whitespace-nowrap text-navbar-text-color sm:visible text-5xl sm:text-7xl roboto"
>
nebula. nebula.
</h1> </h1>
</div> </div>
@ -37,163 +46,188 @@ import { VERSION } from "astro:env/client";
<iframe <iframe
id="neb-iframe" id="neb-iframe"
class="hidden z-100 w-full h-full absolute top-0 bottom-0 bg-primary" class="hidden z-100 w-full h-full absolute top-0 bottom-0 bg-primary"
src="/loading" src="/loading"></iframe>
></iframe> <div
<div id="version" class="flex flex-row w-full absolute bottom-4 pr-4 pl-4 text-text-color h-6 justify-between font-roboto"> id="version"
<p> Version: { VERSION } </p> class="flex flex-row w-full absolute bottom-4 pr-4 pl-4 text-text-color h-6 justify-between font-roboto"
<p> &copy; Nebula Services 2024 </p> >
<p>Version: {VERSION}</p>
<p>&copy; Nebula Services 2024</p>
</div> </div>
</div> </div>
</Layout> </Layout>
<script> <script>
import { initSw, setTransport, loadProxyScripts } from "@utils/registerSW.ts"; //../../utils/registerSW.ts import { initSw, setTransport, loadProxyScripts } from "@utils/registerSW.ts"; //../../utils/registerSW.ts
import { pageLoad } from "@utils/events"; import { pageLoad } from "@utils/events";
import { RammerheadEncode } from "@rubynetwork/rammerhead-browser"; import { RammerheadEncode } from "@rubynetwork/rammerhead-browser";
import { SupportedSites } from "@utils/siteSupport"; import { SupportedSites } from "@utils/siteSupport";
import { import {
SearchEngines, SearchEngines,
Settings, Settings,
cloak, cloak,
settings settings,
} from "@utils/settings/index"; } from "@utils/settings/index";
import { search } from "@utils/search.ts"; //../../utils/search.ts import { search } from "@utils/search.ts"; //../../utils/search.ts
import { client as libcurlClient } from "@utils/libcurl"; import { client as libcurlClient } from "@utils/libcurl";
type Suggestion = { type Suggestion = {
phrase: string; phrase: string;
}; };
async function proxy(term: string, rh: boolean) { async function proxy(term: string, rh: boolean) {
const searchEngine = localStorage.getItem(Settings.ProxySettings.searchEngine); const searchEngine = localStorage.getItem(
Settings.ProxySettings.searchEngine
);
const openIn = localStorage.getItem(Settings.ProxySettings.openIn); const openIn = localStorage.getItem(Settings.ProxySettings.openIn);
let proxyUrl: any = __uv$config!.prefix + __uv$config.encodeUrl!(search(term, searchEngine ? SearchEngines[searchEngine] : SearchEngines.ddg)); let proxyUrl: any =
__uv$config!.prefix +
__uv$config.encodeUrl!(
search(
term,
searchEngine ? SearchEngines[searchEngine] : SearchEngines.ddg
)
);
if (rh) { if (rh) {
proxyUrl = await RammerheadEncode(search(term, searchEngine ? SearchEngines[searchEngine] : SearchEngines.ddg)); proxyUrl = await RammerheadEncode(
search(
term,
searchEngine ? SearchEngines[searchEngine] : SearchEngines.ddg
)
);
} }
if (openIn === "a:b" || openIn === "blob") { if (openIn === "a:b" || openIn === "blob") {
return cloak(openIn as string, "https://google.com", `${window.location.origin}${proxyUrl}`); return cloak(
} openIn as string,
else if (openIn === "direct") { "https://google.com",
`${window.location.origin}${proxyUrl}`
);
} else if (openIn === "direct") {
return (window.location.href = proxyUrl as string); return (window.location.href = proxyUrl as string);
} } else {
else {
return proxyUrl; return proxyUrl;
} }
} }
async function uv(iframe: HTMLIFrameElement, term: string) { async function uv(iframe: HTMLIFrameElement, term: string) {
const conn = await loadProxyScripts(); const conn = await loadProxyScripts();
await setTransport(conn, localStorage.getItem(Settings.ProxySettings.transport) as string); await setTransport(
const sw = await initSw(); conn,
await settings.marketPlaceSettings.handlePlugins(sw); localStorage.getItem(Settings.ProxySettings.transport) as string
iframe.classList.remove("hidden"); );
const url = await proxy(term, false); const sw = await initSw();
if (url) { await settings.marketPlaceSettings.handlePlugins(sw);
iframe.src = url; iframe.classList.remove("hidden");
} const url = await proxy(term, false);
if (url) {
iframe.src = url;
}
} }
async function rh(iframe: HTMLIFrameElement, term: string) { async function rh(iframe: HTMLIFrameElement, term: string) {
iframe.classList.remove("hidden"); iframe.classList.remove("hidden");
const url = await proxy(term, true); const url = await proxy(term, true);
if (url) { if (url) {
iframe.src = "/" + url as string; iframe.src = ("/" + url) as string;
} }
} }
//we need to rerun this on every page load //we need to rerun this on every page load
pageLoad(async () => { pageLoad(async () => {
const input = document.getElementById("nebula-input") as HTMLInputElement; const input = document.getElementById("nebula-input") as HTMLInputElement;
const iframe = document.getElementById("neb-iframe") as HTMLIFrameElement; const iframe = document.getElementById("neb-iframe") as HTMLIFrameElement;
const omnibox = document.getElementById("omnibox") as HTMLDivElement; const omnibox = document.getElementById("omnibox") as HTMLDivElement;
const copyright = document.getElementById("version") as HTMLDivElement; const copyright = document.getElementById("version") as HTMLDivElement;
input?.addEventListener("keypress", async function (event: any) { input?.addEventListener("keypress", async function (event: any) {
if (event.key === "Enter") { if (event.key === "Enter") {
copyright.classList.add("hidden"); copyright.classList.add("hidden");
if (localStorage.getItem(Settings.ProxySettings.proxy) === "automatic") { if (
const key = SupportedSites[input?.value]; localStorage.getItem(Settings.ProxySettings.proxy) === "automatic"
switch(key) { ) {
case "uv": const key = SupportedSites[input?.value];
uv(iframe, input?.value); switch (key) {
break; case "uv":
case "rh": uv(iframe, input?.value);
rh(iframe, input?.value); break;
break; case "rh":
default: rh(iframe, input?.value);
uv(iframe, input?.value); break;
break; default:
} uv(iframe, input?.value);
} break;
else if (localStorage.getItem(Settings.ProxySettings.proxy) === "uv") {
uv(iframe, input?.value);
}
else if (localStorage.getItem(Settings.ProxySettings.proxy) === "rh") {
rh(iframe, input?.value);
} }
} else if (
localStorage.getItem(Settings.ProxySettings.proxy) === "uv"
) {
uv(iframe, input?.value);
} else if (
localStorage.getItem(Settings.ProxySettings.proxy) === "rh"
) {
rh(iframe, input?.value);
} }
}); }
input?.addEventListener("input", async function () { });
omnibox.innerHTML = ""; input?.addEventListener("input", async function () {
const value = input?.value; omnibox.innerHTML = "";
input.classList.remove("rounded-b-2xl"); const value = input?.value;
omnibox.classList.remove("hidden"); input.classList.remove("rounded-b-2xl");
if (value.length === 0) { omnibox.classList.remove("hidden");
input.classList.add("rounded-b-2xl"); if (value.length === 0) {
omnibox.classList.add("hidden"); input.classList.add("rounded-b-2xl");
} omnibox.classList.add("hidden");
if (value.length >= 3) { }
await libcurlClient.initLibcurl(); if (value.length >= 3) {
const data = await libcurlClient.fetchFromLibcurl( await libcurlClient.initLibcurl();
`https://api.duckduckgo.com/ac?q=${encodeURIComponent(value)}&format=json`, const data = (await libcurlClient.fetchFromLibcurl(
'json' `https://api.duckduckgo.com/ac?q=${encodeURIComponent(value)}&format=json`,
) as []; "json"
const filteredData = data.slice(0,8); //Trim to only about 8 results. Any more and our omnibox dies )) as [];
if (filteredData) { const filteredData = data.slice(0, 8); //Trim to only about 8 results. Any more and our omnibox dies
omnibox.innerHTML = ""; if (filteredData) {
filteredData.map((results: Suggestion) => { omnibox.innerHTML = "";
let span = document.createElement("span"); filteredData.map((results: Suggestion) => {
let pTag = document.createElement("p"); let span = document.createElement("span");
span.classList.add( let pTag = document.createElement("p");
"cursor-pointer", span.classList.add(
"font-roboto", "cursor-pointer",
"border-b", "font-roboto",
"border-input-border-color", "border-b",
"last:rounded-b-xl", "border-input-border-color",
"last:border-none", "last:rounded-b-xl",
"text-ellipsis", "last:border-none",
"whitespace-nowrap", "text-ellipsis",
"w-full", "whitespace-nowrap",
"text-input-text", "w-full",
"h-9", "text-input-text",
"text-xl", "h-9",
"text-align-center", "text-xl",
"overflow-hidden", "text-align-center",
"flex", "overflow-hidden",
"items-center", "flex",
"justify-center", "items-center",
"hover:bg-lighter", "justify-center",
"active:bg-primary" "hover:bg-lighter",
); "active:bg-primary"
span.addEventListener("click", function () { );
//When the box is clicked, we want to fill the omnibox and hit enter. This allows us to re-use the existing event listener on the input. span.addEventListener("click", function () {
const event = new KeyboardEvent("keypress", { //When the box is clicked, we want to fill the omnibox and hit enter. This allows us to re-use the existing event listener on the input.
key: "Enter", const event = new KeyboardEvent("keypress", {
code: "Enter", key: "Enter",
which: 13, code: "Enter",
keyCode: 13, which: 13,
}); keyCode: 13,
input.value = results.phrase;
input.dispatchEvent(event);
}); });
pTag.classList.add( input.value = results.phrase;
"cursor-pointer", input.dispatchEvent(event);
"text-ellipsis",
"text-center",
"w-full",
"overflow-hidden",
"whitespace-nowrap"
);
pTag.innerText = results.phrase;
span.appendChild(pTag);
omnibox.appendChild(span);
}); });
} pTag.classList.add(
"cursor-pointer",
"text-ellipsis",
"text-center",
"w-full",
"overflow-hidden",
"whitespace-nowrap"
);
pTag.innerText = results.phrase;
span.appendChild(pTag);
omnibox.appendChild(span);
});
} }
}); }
});
}); });
</script> </script>