From 55edefd906253c27e2c1028d8a59663b1e5e077b Mon Sep 17 00:00:00 2001 From: not-nullptr Date: Sat, 16 Mar 2024 02:44:43 +0000 Subject: [PATCH] fix fonts, colors, etc --- src/app.html | 2 +- src/app.pcss | 10 +-- src/assets/fonts/RocGroteskWideMedium.ttf | Bin 63924 -> 0 bytes src/routes/+layout.svelte | 8 +++ src/routes/+page.svelte | 7 +- src/routes/account/+layout.svelte | 25 ++++--- src/routes/account/+page.svelte | 16 ++--- src/routes/account/friends/+page.svelte | 10 +++ src/routes/account/lobbies/+page.server.ts | 7 ++ src/routes/account/lobbies/+page.svelte | 10 ++- src/routes/account/settings/+page.svelte | 7 -- src/routes/api/user/+server.ts | 2 +- .../{+page.server.ts => +layout.server.ts} | 5 +- src/routes/blog/new/+page.svelte | 9 +++ src/routes/jwt/external/key.pem/+server.ts | 47 +++++++++++++ src/routes/jwt/internal/+server.ts | 16 +++++ src/routes/lobby/+server.ts | 65 ++++++++++++++++++ src/routes/lobby/[id]/+server.ts | 30 ++++++++ src/routes/profile/+server.ts | 11 +++ 19 files changed, 242 insertions(+), 45 deletions(-) delete mode 100644 src/assets/fonts/RocGroteskWideMedium.ttf create mode 100644 src/routes/account/friends/+page.svelte create mode 100644 src/routes/account/lobbies/+page.server.ts delete mode 100644 src/routes/account/settings/+page.svelte rename src/routes/blog/{+page.server.ts => +layout.server.ts} (92%) create mode 100644 src/routes/jwt/external/key.pem/+server.ts create mode 100644 src/routes/jwt/internal/+server.ts create mode 100644 src/routes/lobby/+server.ts create mode 100644 src/routes/lobby/[id]/+server.ts create mode 100644 src/routes/profile/+server.ts diff --git a/src/app.html b/src/app.html index 67052a8..2edde36 100644 --- a/src/app.html +++ b/src/app.html @@ -7,7 +7,7 @@ diff --git a/src/app.pcss b/src/app.pcss index 57b54d3..64b0630 100644 --- a/src/app.pcss +++ b/src/app.pcss @@ -4,14 +4,6 @@ @tailwind components; @tailwind utilities; -@font-face { - font-family: "Roc Grotesk"; - src: url(./assets/fonts/RocGroteskWideMedium.ttf) format("truetype"); - font-weight: 500; - font-style: normal; - font-display: swap; -} - @font-face { font-family: "Consolas"; src: url(./assets/fonts/Consolas.ttf) format("truetype"); @@ -37,7 +29,7 @@ html { h1, h2, h3 { - font-family: "Roc Grotesk", sans-serif; + font-family: "Outfit", sans-serif; } ::selection { diff --git a/src/assets/fonts/RocGroteskWideMedium.ttf b/src/assets/fonts/RocGroteskWideMedium.ttf deleted file mode 100644 index f59a054a8091567865488ce4e591743c888515f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63924 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 +
+ +
+
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 3b92465..b479699 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -40,7 +40,7 @@
-

- suyu is an open-source, non-profit Switch emulator +

+ suyu is a fully open-source + Switch emulator

suyu is a familiar C++ based Switch emulator with a focus on compatibility. Completely free diff --git a/src/routes/account/+layout.svelte b/src/routes/account/+layout.svelte index a5f4877..ab03edf 100644 --- a/src/routes/account/+layout.svelte +++ b/src/routes/account/+layout.svelte @@ -22,7 +22,7 @@ const navItems: NavItem[] = [ { - name: "Online Services", + name: "Multiplayer", href: "/account", }, { @@ -30,8 +30,8 @@ href: "/account/lobbies", }, { - name: "Settings", - href: "/account/settings", + name: "Friends", + href: "/account/friends", }, ]; @@ -54,7 +54,11 @@ const pillBounds = indicator.getBoundingClientRect(); indicator.style.transform = `translateX(${bounds.left - navBounds.left}px)`; indicator.style.width = `${bounds.width}px`; - if ((selected !== 0 && selected !== navItems.length - 1) || $reducedMotion) return; + if ( + // (selected !== 0 && selected !== navItems.length - 1) || + $reducedMotion + ) + return; indicator.offsetHeight; const transformFactor = bounds.left - pillBounds.left; navBar.animate( @@ -64,23 +68,18 @@ easing: "ease-out", }, { - transform: `translateX(${transformFactor / 100}px)`, - offset: 0.1, + transform: `translateX(${transformFactor / 50}px)`, + offset: 0.4, easing: "ease-out", }, - { - transform: `translateX(${-transformFactor / 200}px)`, - offset: 0.8, - easing: "ease-in", - }, { transform: "translateX(0px)", easing: "ease-in", }, ], { - duration: 500, - delay: 170, + duration: 360, + delay: 0, }, ); } diff --git a/src/routes/account/+page.svelte b/src/routes/account/+page.svelte index a4b2302..2854996 100644 --- a/src/routes/account/+page.svelte +++ b/src/routes/account/+page.svelte @@ -52,12 +52,14 @@ stroke="white" /> -

- suyu Online Services -

+

Multiplayer

- Your token should be kept private. If you believe it has been compromised, please - contact us immediately. + Hey, {data.user.username}! This is your token, used to authenticate your identity within suyu. Your token + should be kept private. If you believe it has been compromised, please contact us + immediately.

-
diff --git a/src/routes/account/friends/+page.svelte b/src/routes/account/friends/+page.svelte new file mode 100644 index 0000000..69efca5 --- /dev/null +++ b/src/routes/account/friends/+page.svelte @@ -0,0 +1,10 @@ +
+
+

Friends

+

+ TBD: madeline has no friends :( ~maddie/null +

+
+
diff --git a/src/routes/account/lobbies/+page.server.ts b/src/routes/account/lobbies/+page.server.ts new file mode 100644 index 0000000..c5d6ecf --- /dev/null +++ b/src/routes/account/lobbies/+page.server.ts @@ -0,0 +1,7 @@ +import { RoomManager } from "$lib/server/class/Room.js"; + +export function load({ request }) { + return { + rooms: RoomManager.getRooms().map((r) => r.toJSON()), + }; +} diff --git a/src/routes/account/lobbies/+page.svelte b/src/routes/account/lobbies/+page.svelte index c5d1511..b5b62c9 100644 --- a/src/routes/account/lobbies/+page.svelte +++ b/src/routes/account/lobbies/+page.svelte @@ -1,7 +1,15 @@ + +
- LOBBIES YEHAHH + {#each data.rooms as room} +

{room.name}

+ {/each}
diff --git a/src/routes/account/settings/+page.svelte b/src/routes/account/settings/+page.svelte deleted file mode 100644 index ee350be..0000000 --- a/src/routes/account/settings/+page.svelte +++ /dev/null @@ -1,7 +0,0 @@ -
-
- SETTTTTINGGGASSS WOOOOOOOOOOOO -
-
diff --git a/src/routes/api/user/+server.ts b/src/routes/api/user/+server.ts index e37b0ec..b53dc99 100644 --- a/src/routes/api/user/+server.ts +++ b/src/routes/api/user/+server.ts @@ -39,7 +39,7 @@ export async function POST({ request, getClientAddress }) { error: "missing fields", }); } - if (body.username.length < 3 || body.username.length > 24) { + if (body.username.length < 3 || body.username.length > 24 || body.username.trim() === "") { return json({ success: false, error: "invalid username", diff --git a/src/routes/blog/+page.server.ts b/src/routes/blog/+layout.server.ts similarity index 92% rename from src/routes/blog/+page.server.ts rename to src/routes/blog/+layout.server.ts index bac9c59..ddd65ad 100644 --- a/src/routes/blog/+page.server.ts +++ b/src/routes/blog/+layout.server.ts @@ -36,9 +36,12 @@ export async function load({ request }) { const user = await useModeratorAuth(request); return { posts, - userInfo: JSON.parse(JSON.stringify(user)) as { + userInfo: (JSON.parse(JSON.stringify(user)) as { user: SuyuUser | null; isModerator: boolean; + }) || { + user: null, + isModerator: false, }, }; } diff --git a/src/routes/blog/new/+page.svelte b/src/routes/blog/new/+page.svelte index 8e8b122..7f28fc4 100644 --- a/src/routes/blog/new/+page.svelte +++ b/src/routes/blog/new/+page.svelte @@ -1,6 +1,9 @@
diff --git a/src/routes/jwt/external/key.pem/+server.ts b/src/routes/jwt/external/key.pem/+server.ts new file mode 100644 index 0000000..ef8c292 --- /dev/null +++ b/src/routes/jwt/external/key.pem/+server.ts @@ -0,0 +1,47 @@ +import { json } from "$lib/server/util/index.js"; + +export function GET({ request }) { + return new Response( + `-----BEGIN CERTIFICATE----- +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +-----END CERTIFICATE-----`, + { + headers: { + "content-type": "text/plain", + }, + }, + ); +} + +export function POST({ request }) { + return new Response(); +} diff --git a/src/routes/jwt/internal/+server.ts b/src/routes/jwt/internal/+server.ts new file mode 100644 index 0000000..ba144e7 --- /dev/null +++ b/src/routes/jwt/internal/+server.ts @@ -0,0 +1,16 @@ +import { PRIVATE_KEY } from "$lib/server/secrets/secrets.json"; +import { useAuth } from "$lib/util/api/index.js"; +import jwt from "jsonwebtoken"; + +export async function POST({ request }) { + const userKey = `${request.headers.get("x-username")}:${request.headers.get("x-token")}`; + const user = await useAuth(userKey); + const token = jwt.sign({ ...user, apiKey: userKey }, Buffer.from(PRIVATE_KEY), { + algorithm: "RS256", + }); + return new Response(token, { + headers: { + "content-type": "text/html", + }, + }); +} diff --git a/src/routes/lobby/+server.ts b/src/routes/lobby/+server.ts new file mode 100644 index 0000000..dd223c5 --- /dev/null +++ b/src/routes/lobby/+server.ts @@ -0,0 +1,65 @@ +import { Room, RoomManager } from "$lib/server/class/Room"; +import { userRepo } from "$lib/server/repo/index.js"; +import { SuyuUser } from "$lib/server/schema"; +import { PUBLIC_KEY } from "$lib/server/secrets/secrets.json"; +import { json } from "$lib/server/util"; +import { useAuth } from "$lib/util/api/index.js"; +import type { IJwtData } from "$types/auth.js"; +import type { IRoom, LobbyResponse } from "$types/rooms"; +import jwt from "jsonwebtoken"; + +export async function GET({ request }) { + return json({ + rooms: RoomManager.getRooms().map((r) => r.toJSON()), + }); +} + +/* credit to janeberru for showing the shape of this data */ +export async function POST({ request, getClientAddress }) { + // TODO: per-ip room limit + const body: IRoom = await request.json(); + /* description may contain "### END DESCRIPTION ###" on its own line. if it does, get all lines after that */ + const parsedDescription = body.description.split("### END DESCRIPTION ###"); + console.log(parsedDescription); + const description = parsedDescription?.slice(1)?.join("### END DESCRIPTION ###") || ""; + const opts: { [key: string]: string } = {}; + description.split("\n").forEach((line) => { + const [key, ...values] = line.split("="); + const value = values.join("=").trim(); + if (!key || !value) return; + opts[key] = value; + }); + if (opts.ip) { + if ( + !opts.ip.match( + /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/, + ) + ) { + return new Response(null, { status: 400 }); + } + } + const token = request.headers.get("authorization"); + if (!token) return new Response(null, { status: 401 }); + // TODO: jwt utils which type and validate automatically + const user = await useAuth(token); + console.log(user); + if (!user) return new Response(null, { status: 401 }); + const room = RoomManager.createRoom({ + name: body.name, + description: parsedDescription[0] || "", + gameName: body.preferredGameName, + gameId: body.preferredGameId, + players: [ + { + gameId: 0, + gameName: "", + nickname: user.username, + }, + ], + maxPlayers: body.maxPlayers, + ip: `${opts.ip || getClientAddress().split(":").at(-1)}:${body.port}`, + host: user, + hasPassword: body.hasPassword || false, + }); + return json(room.toJSON()); +} diff --git a/src/routes/lobby/[id]/+server.ts b/src/routes/lobby/[id]/+server.ts new file mode 100644 index 0000000..b85cea8 --- /dev/null +++ b/src/routes/lobby/[id]/+server.ts @@ -0,0 +1,30 @@ +import { RoomManager } from "$lib/server/class/Room"; +import { json } from "$lib/server/util/index.js"; +import { useAuth } from "$lib/util/api/index.js"; + +/* thanks again janeberru for the shape of this data */ +export async function POST({ request, params }) { + const body = await request.json(); + const { id } = params; + const room = RoomManager.getRoom(id); + if (!room) return new Response(null, { status: 500 }); + const user = await useAuth(request.headers.get("authorization") || ""); + if (!user) return new Response(null, { status: 401 }); + if (user.id !== room.host.id) return new Response(null, { status: 401 }); + if (body.players.length === 0 && room.roomInfo.owner) { + console.log(room.roomInfo.players); + room.setPlayerList([{ gameId: 0, gameName: "", nickname: room.roomInfo.owner }]); + } + return json({ message: "Lobby updated successfully" }); +} + +export async function DELETE({ request, params }) { + const { id } = params; + const room = RoomManager.getRoom(id); + if (!room) return new Response(null, { status: 500 }); + const user = await useAuth(request.headers.get("authorization") || ""); + if (!user) return new Response(null, { status: 401 }); + if (user.id !== room.host.id) return new Response(null, { status: 401 }); + room.delete(); + return json(room.toJSON()); +} diff --git a/src/routes/profile/+server.ts b/src/routes/profile/+server.ts new file mode 100644 index 0000000..a5c82c2 --- /dev/null +++ b/src/routes/profile/+server.ts @@ -0,0 +1,11 @@ +import { json } from "$lib/server/util/index"; +import { useAuth } from "$lib/util/api/index.js"; + +export async function GET({ request }) { + const user = await useAuth(request.headers.get("authorization") || ""); + console.log(user); + if (!user) return new Response(null, { status: 401 }); + return json({ + username: user.username, + }); +}