diff --git a/package-lock.json b/package-lock.json index 4679e89..44bbcbb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,12 +31,12 @@ "get-relative-path": "^1.0.2", "get-stream": "^6.0.1", "h3": "^1.12.0", - "heatsync": "^2.7.2", + "heatsync": "^2.7.0", "lru-cache": "^10.4.3", "minimist": "^1.2.8", "prettier-bytes": "^1.0.4", "sharp": "^0.33.4", - "snowtransfer": "^0.12.0", + "snowtransfer": "^0.11.0", "stream-mime-type": "^1.0.2", "try-to-catch": "^3.0.1", "uqr": "^0.1.2", @@ -1075,11 +1075,10 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.19.76", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.76.tgz", - "integrity": "sha512-yvR7Q9LdPz2vGpmpJX5LolrgRdWvB67MJKDPSgIIzpFbaf9a1j/f5DnLp5VDyHGMR0QZHlTr1afsD87QCXFHKw==", + "version": "18.19.75", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.75.tgz", + "integrity": "sha512-UIksWtThob6ZVSyxcOqCLOUNg/dyO1Qvx4McgeuhrEtHTLFTf7BBhEazaE4K806FGTPtzd/2sE90qn4fVr7cyw==", "dev": true, - "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } @@ -1413,13 +1412,12 @@ } }, "node_modules/cloudstorm": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/cloudstorm/-/cloudstorm-0.11.4.tgz", - "integrity": "sha512-fk0tAyZmUBWrxELyXaKh19s1RJucmhmvTMfB/LrvdRHdUvc20VkD7qCrFaQHSQ/+kzwhSHVY43zNAjtz93pH9A==", - "license": "MIT", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/cloudstorm/-/cloudstorm-0.11.2.tgz", + "integrity": "sha512-LuKey+nTp5fEGH5TdCxCUWSG1VMcXKV57rsFvGi/XLpdPT1LUTlc5TmCONAaKzy2uZFJm9EG+iIB2Vq+uBqgog==", "dependencies": { "discord-api-types": "^0.37.119", - "snowtransfer": "^0.12.0" + "snowtransfer": "^0.11.0" }, "engines": { "node": ">=16.15.0" @@ -1870,9 +1868,9 @@ } }, "node_modules/heatsync": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/heatsync/-/heatsync-2.7.2.tgz", - "integrity": "sha512-1djRg4eufv5q+CRy5SuZSiV3j53KIDSGkDubJB+vXY1OE+AnTkw5HIJxi+0vEjHjX+wbH5syYQunQ/ElAgoEmg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/heatsync/-/heatsync-2.7.0.tgz", + "integrity": "sha512-9ILOyyHFZKfIrqBmNz+fwKd+zupFE2UqFZ9k4FjRcMjNDp7GtW+K9n2htXLy3CwdDTRd6NV6BPxKvU51UqKIJA==", "license": "MIT", "dependencies": { "backtracker": "^4.0.0" @@ -2681,10 +2679,9 @@ } }, "node_modules/snowtransfer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.12.0.tgz", - "integrity": "sha512-EmVTAeSXtA7ZlTqwmZxe5JwRTm4FOXEOqMOzGu8fdVSoqXjcWgQ8IfaIRu/54FamOMjOmcxnpTyNPj5MUqWxpA==", - "license": "MIT", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.11.0.tgz", + "integrity": "sha512-07rvRnCtXdL/E3PmKTS/zHVlIIIWizKh7YzsUxN2bmX1Fr5odFgZ08J0/dE1YL6XmsbpmEB2r4LBAfdCGzKs7w==", "dependencies": { "discord-api-types": "^0.37.119" }, @@ -3321,10 +3318,9 @@ } }, "node_modules/zod": { - "version": "3.24.2", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", - "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", - "license": "MIT", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index df954f7..83dc636 100644 --- a/package.json +++ b/package.json @@ -40,12 +40,12 @@ "get-relative-path": "^1.0.2", "get-stream": "^6.0.1", "h3": "^1.12.0", - "heatsync": "^2.7.2", + "heatsync": "^2.7.0", "lru-cache": "^10.4.3", "minimist": "^1.2.8", "prettier-bytes": "^1.0.4", "sharp": "^0.33.4", - "snowtransfer": "^0.12.0", + "snowtransfer": "^0.11.0", "stream-mime-type": "^1.0.2", "try-to-catch": "^3.0.1", "uqr": "^0.1.2", diff --git a/src/d2m/actions/set-presence.js b/src/d2m/actions/set-presence.js index f26668f..d16835e 100644 --- a/src/d2m/actions/set-presence.js +++ b/src/d2m/actions/set-presence.js @@ -38,7 +38,7 @@ const guildPresenceSetting = new class { } } -class Presence extends sync.reloadClassMethods(() => Presence) { +class Presence extends sync.ReloadableClass { /** @type {string} */ userID /** @type {{presence: "online" | "offline" | "unavailable", status_msg?: string}} */ data /** @private @type {?string | undefined} */ mxid @@ -70,6 +70,7 @@ class Presence extends sync.reloadClassMethods(() => Presence) { }, this.delay * presenceLoopInterval).unref() } } +sync.reloadClassMethods(Presence) const presenceTracker = new class { /** @private @type {Map} userID -> Presence */ presences = sync.remember(() => new Map()) diff --git a/src/web/pug-sync.js b/src/web/pug-sync.js index f49f5a2..56b16fb 100644 --- a/src/web/pug-sync.js +++ b/src/web/pug-sync.js @@ -39,14 +39,7 @@ function render(event, filename, locals) { defaultContentType(event, "text/html; charset=utf-8") const session = await auth.useSession(event) const managed = await auth.getManagedGuilds(event) - const rel = (to, paramsObject) => { - let result = getRelativePath(event.path, to) - if (paramsObject) { - const params = new URLSearchParams(paramsObject) - result += "?" + params.toString() - } - return result - } + const rel = x => getRelativePath(event.path, x) return template(Object.assign({}, getQuery(event), // Query parameters can be easily accessed on the top level but don't allow them to overwrite anything globals, // Globals diff --git a/src/web/pug/guild_not_linked.pug b/src/web/pug/guild_not_linked.pug index 771eca0..0e2a2d4 100644 --- a/src/web/pug/guild_not_linked.pug +++ b/src/web/pug/guild_not_linked.pug @@ -18,10 +18,8 @@ block body div != icons.Icons.IconInfo div - - const self = `@${reg.sender_localpart}:${reg.ooye.server_name}` strong You picked self-service mode .mt4 To complete setup, you need to manually choose a Matrix space to link with #[strong= guild.name]. - .mt4 On Matrix, invite #[code.s-code-block: a.fc-black.s-link(href=`https://matrix.to/#/${self}` target="_blank")= self] to a space. Then you can pick the space on this page. h3.mt32.fs-category Choose a space @@ -35,12 +33,13 @@ block body else if session.data.mxid tr - td.p16 Invite the bridge to a space, and the space will show up here. + - const self = `@${reg.sender_localpart}:${reg.ooye.server_name}` + td.p16 On Matrix, invite #[code.s-code-block: a.s-link(href=`https://matrix.to/#/${self}` target="_blank")= self] to a space. Then you can pick it from this list. else tr td.d-flex.ai-center.pl16.g16 | You need to log in with Matrix first. - a.s-btn.s-btn__matrix.s-btn__outlined(href=rel(`/log-in-with-matrix`, {next: `./guild?guild_id=${guild_id}`})) Log in with Matrix + a.s-btn.s-btn__matrix.s-btn__outlined(href=rel("/log-in-with-matrix")) Log in with Matrix h3.mt48.fs-category Auto-create .s-card diff --git a/src/web/pug/log-in-with-matrix.pug b/src/web/pug/log-in-with-matrix.pug index 3f7da91..6fe2947 100644 --- a/src/web/pug/log-in-with-matrix.pug +++ b/src/web/pug/log-in-with-matrix.pug @@ -7,8 +7,6 @@ block body .d-flex.g16#form-container .fl-grow1 form.d-flex.gy16.fd-column(method="post" action="/api/log-in-with-matrix" hx-post="/api/log-in-with-matrix" hx-indicator="#log-in-button" hx-select="#ok" hx-target="#form-container") - if next - input(type="hidden" name="next" value=next) .d-flex.gy4.fd-column label.s-label(for="mxid") Your Matrix ID input.fl-grow1.s-input.wmx3#mxid(name="mxid" required placeholder="@user:example.org") diff --git a/src/web/routes/log-in-with-matrix.js b/src/web/routes/log-in-with-matrix.js index b5c741c..70a60bb 100644 --- a/src/web/routes/log-in-with-matrix.js +++ b/src/web/routes/log-in-with-matrix.js @@ -17,12 +17,10 @@ const auth = sync.require("../auth") const schema = { form: z.object({ - mxid: z.string(), - next: z.string().optional() + mxid: z.string() }), token: z.object({ - token: z.string().optional(), - next: z.string().optional() + token: z.string() }) } @@ -45,16 +43,17 @@ const validToken = new LRUCache({max: 200}) */ as.router.get("/log-in-with-matrix", defineEventHandler(async event => { - let {token, next} = await getValidatedQuery(event, schema.token.parse) + const parsed = await getValidatedQuery(event, schema.token.safeParse) - if (!token) { + if (!parsed.success) { // We are in the first request and need to tell them to input their mxid - return pugSync.render(event, "log-in-with-matrix.pug", {next}) + return pugSync.render(event, "log-in-with-matrix.pug", {}) } const userAgent = getRequestHeader(event, "User-Agent") if (userAgent?.match(/bot/)) throw createError({status: 400, data: "Sorry URL previewer, you can't have this URL."}) + const token = parsed.data.token if (!validToken.has(token)) return sendRedirect(event, `${reg.ooye.bridge_origin}/log-in-with-matrix`, 302) const session = await auth.useSession(event) @@ -64,13 +63,12 @@ as.router.get("/log-in-with-matrix", defineEventHandler(async event => { await session.update({mxid}) - if (!next) next = "./" // open to homepage where they can see they're logged in - return sendRedirect(event, next, 302) + return sendRedirect(event, "./", 302) // open to homepage where they can see they're logged in })) as.router.post("/api/log-in-with-matrix", defineEventHandler(async event => { const api = getAPI(event) - const {mxid, next} = await readValidatedBody(event, schema.form.parse) + const {mxid} = await readValidatedBody(event, schema.form.parse) let roomID = null // Don't extend a duplicate invite for the same user @@ -119,11 +117,7 @@ as.router.post("/api/log-in-with-matrix", defineEventHandler(async event => { validToken.set(token, mxid) console.log(`web log in requested for ${mxid}`) - const paramsObject = {token} - if (next) paramsObject.next = next - const params = new URLSearchParams(paramsObject) - let link = `${reg.ooye.bridge_origin}/log-in-with-matrix?${params.toString()}` - const body = `Hi, this is Out Of Your Element! You just clicked the "log in" button on the website.\nOpen this link to finish: ${link}\nThe link can be used once.` + const body = `Hi, this is Out Of Your Element! You just clicked the "log in" button on the website.\nOpen this link to finish: ${reg.ooye.bridge_origin}/log-in-with-matrix?token=${token}\nThe link can be used once.` await api.sendEvent(roomID, "m.room.message", { msgtype: "m.text", body