diff --git a/bun.lockb b/bun.lockb index 7ff8555..44f564e 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/guestbook/src/main/scala/systems/gaze/guestbook/GuestbookRoutes.scala b/guestbook/src/main/scala/systems/gaze/guestbook/GuestbookRoutes.scala index dc0c608..267120c 100644 --- a/guestbook/src/main/scala/systems/gaze/guestbook/GuestbookRoutes.scala +++ b/guestbook/src/main/scala/systems/gaze/guestbook/GuestbookRoutes.scala @@ -14,38 +14,26 @@ import cats.effect.unsafe.implicits.global import scala.concurrent.duration.FiniteDuration import org.http4s.Uri -class GuestbookRoutes(var guestbookConfig: Guestbook.Config, var websiteUri: Uri): +class GuestbookRoutes( + var guestbookConfig: Guestbook.Config, + var websiteUri: Uri +): val dsl = new Http4sDsl[IO] {} import dsl.* def throttle( - ratelimited: String, amount: Int, per: FiniteDuration )(routes: HttpRoutes[IO]): HttpRoutes[IO] = Throttle .httpRoutes[IO](amount, per)(routes) .unsafeRunSync() - .map((resp) => - // respond with SeeOther and put ratelimited query param - if (resp.status == TooManyRequests) - resp - .withStatus(SeeOther) - .withHeaders( - Location( - (websiteUri / "guestbook") - .withQueryParam("ratelimited", ratelimited) - ) - ) - else - resp - ) def routes( G: Guestbook[IO] ): HttpRoutes[IO] = - val putEntry = HttpRoutes.of[IO] { - case req @ POST -> Root => for { + val putEntry = HttpRoutes.of[IO] { case req @ POST -> Root => + for { entry <- req.as[UrlForm].map { form => val author = form.getFirstOrElse("author", "error") val content = form.getFirstOrElse("content", "error") @@ -56,11 +44,11 @@ class GuestbookRoutes(var guestbookConfig: Guestbook.Config, var websiteUri: Uri resp <- SeeOther(Location(websiteUri / "guestbook")) } yield resp } - val getEntries = HttpRoutes.of[IO] { - case GET -> Root / IntVar(page) => for { + val getEntries = HttpRoutes.of[IO] { case GET -> Root / IntVar(page) => + for { entries <- G.read(guestbookConfig, (page - 1).max(0) * 5, 5) resp <- Ok(entries) } yield resp } - throttle("get", 10, 2.seconds)(getEntries) - <+> throttle("send", 5, 10.seconds)(putEntry) + throttle(30, 2.seconds)(getEntries) + <+> throttle(5, 10.seconds)(putEntry) diff --git a/package.json b/package.json index f5eb99b..e41facc 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,6 @@ "format": "prettier --write ." }, "devDependencies": { - "@sveltejs/adapter-auto": "^3.2.2", - "@sveltejs/adapter-static": "^3.0.2", "@sveltejs/kit": "^2.5.20", "@sveltejs/vite-plugin-svelte": "^3.1.1", "@tailwindcss/forms": "^0.5.7", @@ -45,6 +43,9 @@ "rehype-slug": "^6.0.0" }, "trustedDependencies": [ + "@sveltejs/kit", + "deasync", + "esbuild", "svelte-preprocess" ] } diff --git a/src/lib/fetchHack.mjs b/src/lib/fetchHack.mjs deleted file mode 100644 index e8d25c2..0000000 --- a/src/lib/fetchHack.mjs +++ /dev/null @@ -1,25 +0,0 @@ -// hack/postSync.mjs -/** - ,* @file POST some stuff to a URL. - ,* Usage: one of - ,* echo input | node postSync.mjs - ,* node postSync.mjs - ,*/ - -// The argument count would break if called as a standalone script. -const url = process.argv[2] || process.exit(1); - -const response = await fetch(url, {method:'GET',redirect:'manual'}); -const json = await response.text().then(text => { - try { - const data = JSON.parse(text); - return data - } catch(err) { - return [] - } -}); -console.log(JSON.stringify({ - location: response.headers.get('location'), - status: response.status, - body: json, -})); \ No newline at end of file diff --git a/src/lib/index.ts b/src/lib/index.ts index 856f2b6..e69de29 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1 +0,0 @@ -// place files you want to import through the `$lib` alias in this folder. diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 9d14b9a..ddfd5f2 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -1,8 +1,6 @@ -import { dev } from '$app/environment'; - -export const csr = dev; +export const csr = false; export const ssr = true; -export const prerender = true; +export const prerender = false; export const trailingSlash = 'always'; export async function load({ url }) { diff --git a/src/routes/+page.ts b/src/routes/+page.ts new file mode 100644 index 0000000..c8cacf0 --- /dev/null +++ b/src/routes/+page.ts @@ -0,0 +1 @@ +export const prerender = true; \ No newline at end of file diff --git a/src/routes/about/+layout.ts b/src/routes/about/+layout.ts new file mode 100644 index 0000000..c8cacf0 --- /dev/null +++ b/src/routes/about/+layout.ts @@ -0,0 +1 @@ +export const prerender = true; \ No newline at end of file diff --git a/src/routes/entries/+layout.ts b/src/routes/entries/+layout.ts new file mode 100644 index 0000000..c8cacf0 --- /dev/null +++ b/src/routes/entries/+layout.ts @@ -0,0 +1 @@ +export const prerender = true; \ No newline at end of file diff --git a/src/routes/guestbook/+page.server.ts b/src/routes/guestbook/+page.server.ts index abb7b83..b2c4b0c 100644 --- a/src/routes/guestbook/+page.server.ts +++ b/src/routes/guestbook/+page.server.ts @@ -1,6 +1,6 @@ -import { GUESTBOOK_URL } from '$env/static/private' -import { redirect } from '@sveltejs/kit'; -import {spawnSync} from 'node:child_process' +import { GUESTBOOK_BASE_URL } from '$env/static/private' +import { PUBLIC_BASE_URL } from '$env/static/public' +import { redirect } from '@sveltejs/kit' interface Entry { author: String, @@ -8,51 +8,56 @@ interface Entry { timestamp: number, } -interface FetchResult { - location: string, - status: number, - body: any, -} - -function fetchBlocking(url: string): FetchResult | string { - const spawnResult = spawnSync("bun", ["src/lib/fetchHack.mjs", url]); - const out = spawnResult.stdout.toString(); - try { - return JSON.parse(out) - } catch(err: any) { - return spawnResult.stderr.toString() +export const actions = { + default: async ({ request, cookies }) => { + const body = await request.text() + let respRaw: Response + try { + respRaw = await fetch(`${GUESTBOOK_BASE_URL}`, { method: 'POST', body }) + } catch (err: any) { + cookies.set("sendError", err.toString(), { path: "/guestbook" }) + redirect(303, `${PUBLIC_BASE_URL}/guestbook/`) + } + const ratelimited = respRaw.status === 429 + cookies.set("sendRatelimited", ratelimited.toString(), { path: "/guestbook" }) + redirect(303, `${PUBLIC_BASE_URL}/guestbook/`) } } -export function load({ url }) { +export async function load({ url, fetch, cookies }) { var data = { entries: [] as [number, Entry][], - guestbook_url: GUESTBOOK_URL, - ratelimitedFeat: url.searchParams.get('ratelimited') as string || "", - page: parseInt(url.searchParams.get('page') || "1") || 1, + page: parseInt(url.searchParams.get('page') || "1"), hasNext: false, - fetchError: "", + sendError: cookies.get("sendError") || "", + getError: "", + sendRatelimited: cookies.get('sendRatelimited') || "", + getRatelimited: false, } + // delete the cookies after we get em since we dont really need these more than once + cookies.delete("sendError", { path: "/guestbook" }) + cookies.delete("sendRatelimited", { path: "/guestbook" }) // handle cases where the page query might be a string so we just return back page 1 instead data.page = isNaN(data.page) ? 1 : data.page data.page = Math.max(data.page, 1) - if (data.ratelimitedFeat === "get") { + let respRaw: Response + try { + respRaw = await fetch(GUESTBOOK_BASE_URL + "/" + data.page) + } catch (err: any) { + data.getError = err.toString() return data } - const entriesResp = fetchBlocking(GUESTBOOK_URL + "/" + data.page) - if (typeof entriesResp === "string") { - data.fetchError = entriesResp - return data + data.getRatelimited = respRaw.status === 429 + if (!data.getRatelimited) { + let body: any + try { + body = await respRaw.json() + } catch (err: any) { + data.getError = err.toString() + return data + } + data.entries = body.entries + data.hasNext = body.hasNext } - const locationRaw = entriesResp.status === 303 ? entriesResp.location : null - if (locationRaw !== null && locationRaw.length > 0) { - const location = new URL(locationRaw) - data.ratelimitedFeat = location.searchParams.get('ratelimited') as string || "" - } - if (data.ratelimitedFeat === "get") { - return data - } - data.entries = entriesResp.body.entries - data.hasNext = entriesResp.body.hasNext return data } \ No newline at end of file diff --git a/src/routes/guestbook/+page.svelte b/src/routes/guestbook/+page.svelte index f024858..7f09708 100644 --- a/src/routes/guestbook/+page.svelte +++ b/src/routes/guestbook/+page.svelte @@ -2,7 +2,6 @@ import Window from '../../components/window.svelte'; export let data; - const hasPreviousPage = data.page > 1; const hasNextPage = data.hasNext; @@ -10,11 +9,10 @@
- {@const ratelimited = data.ratelimitedFeat === 'send'}

hia, here is the guestbook if you wanna post anything :)

just be a good human bean pretty please

-
+

###

@@ -42,10 +40,17 @@ value="post" class="text-xl text-ralsei-green-light leading-5 motion-safe:hover:animate-bounce w-fit border-double border-4 p-1 pb-2" /> - {#if ratelimited} + {#if data.sendRatelimited}

you are ratelimited, try again in 30 seconds

{/if}
+ {#if data.sendError} +

got error trying to send post, pls tell me about this

+
+ error +

{data.sendError}

+
+ {/if}
@@ -53,15 +58,15 @@
- {#if data.ratelimitedFeat === 'get'} + {#if data.getRatelimited}

woops, looks like you are being ratelimited, try again in like half a minute :3

- {:else if data.fetchError} + {:else if data.getError}

got error trying to fetch entries, pls tell me about this

error -

{data.fetchError}

+

{data.getError}

{:else} {#each data.entries as [entry_id, entry] (entry_id)}