diff --git a/src/web/pug/guild.pug b/src/web/pug/guild.pug index 9f12d38..536ea4c 100644 --- a/src/web/pug/guild.pug +++ b/src/web/pug/guild.pug @@ -69,11 +69,7 @@ block body .grid--row-start2 button.s-btn.s-btn__filled.htmx-indicator Invite div - - - let size = 105 - let p = new URLSearchParams() - p.set("data", `https://bridge.cadence.moe/invite?nonce=${nonce}`) - img(width=size height=size src=rel(`/qr?${p}`)) + != svg h2.mt48.fs-headline1 Moderation diff --git a/src/web/routes/guild.js b/src/web/routes/guild.js index 6916d56..5944131 100644 --- a/src/web/routes/guild.js +++ b/src/web/routes/guild.js @@ -6,6 +6,7 @@ const {H3Event, defineEventHandler, sendRedirect, useSession, createError, getVa const {randomUUID} = require("crypto") const {LRUCache} = require("lru-cache") const Ty = require("../../types") +const uqr = require("uqr") const {discord, as, sync, select} = require("../../passthrough") /** @type {import("../pug-sync")} */ @@ -93,10 +94,17 @@ as.router.get("/guild", defineEventHandler(async event => { const nonce = randomUUID() validNonce.set(nonce, guild_id) + const data = `${reg.ooye.bridge_origin}/invite?nonce=${nonce}` + // necessary to scale the svg pixel-perfectly on the page + // https://github.com/unjs/uqr/blob/244952a8ba2d417f938071b61e11fb1ff95d6e75/src/svg.ts#L24 + const generatedSvg = uqr.renderSVG(data, {pixelSize: 3}) + const svg = generatedSvg.replace(/viewBox="0 0 ([0-9]+) ([0-9]+)"/, `data-nonce="${nonce}" width="$1" height="$2" $&`) + assert.notEqual(svg, generatedSvg) + // Unlinked guild if (!row) { const links = getChannelRoomsLinks(guild_id, []) - return pugSync.render(event, "guild.pug", {guild, guild_id, nonce, ...links}) + return pugSync.render(event, "guild.pug", {guild, guild_id, svg, ...links}) } // Linked guild @@ -105,7 +113,7 @@ as.router.get("/guild", defineEventHandler(async event => { const banned = await api.getMembers(row.space_id, "ban") const rooms = await api.getFullHierarchy(row.space_id) const links = getChannelRoomsLinks(guild_id, rooms) - return pugSync.render(event, "guild.pug", {guild, guild_id, nonce, mods, banned, ...links, ...row}) + return pugSync.render(event, "guild.pug", {guild, guild_id, svg, mods, banned, ...links, ...row}) })) as.router.get("/invite", defineEventHandler(async event => { diff --git a/src/web/routes/guild.test.js b/src/web/routes/guild.test.js index f89dfee..3952d14 100644 --- a/src/web/routes/guild.test.js +++ b/src/web/routes/guild.test.js @@ -78,7 +78,7 @@ test("web guild: can view bridged guild", async t => { } }) t.match(content, / { - const {data} = await getValidatedQuery(event, schema.qr.parse) - return new Response(uqr.renderSVG(data, {pixelSize: 3}), {headers: {"content-type": "image/svg+xml"}}) -})) diff --git a/src/web/routes/qr.test.js b/src/web/routes/qr.test.js deleted file mode 100644 index 5b17f87..0000000 --- a/src/web/routes/qr.test.js +++ /dev/null @@ -1,17 +0,0 @@ -const {test} = require("supertape") -const {router} = require("../../../test/web") -const getStream = require("get-stream") - -test("web qr: returns svg", async t => { - /** @type {Response} */ - const res = await router.test("get", "/qr?data=hello+world", { - params: { - server_name: "cadence.moe", - media_id: "1" - } - }) - t.equal(res.status, 200) - t.equal(res.headers.get("content-type"), "image/svg+xml") - const content = await getStream(res.body) - t.match(content, /