Compare commits

..

No commits in common. "efd7cb3fd412aa364eeb4568faf9fabb1839c174" and "98ff9b0e8fc995e9d8e9d3d7c39185d978f85982" have entirely different histories.

7 changed files with 35 additions and 54 deletions

40
package-lock.json generated
View file

@ -31,12 +31,12 @@
"get-relative-path": "^1.0.2", "get-relative-path": "^1.0.2",
"get-stream": "^6.0.1", "get-stream": "^6.0.1",
"h3": "^1.12.0", "h3": "^1.12.0",
"heatsync": "^2.7.2", "heatsync": "^2.7.0",
"lru-cache": "^10.4.3", "lru-cache": "^10.4.3",
"minimist": "^1.2.8", "minimist": "^1.2.8",
"prettier-bytes": "^1.0.4", "prettier-bytes": "^1.0.4",
"sharp": "^0.33.4", "sharp": "^0.33.4",
"snowtransfer": "^0.12.0", "snowtransfer": "^0.11.0",
"stream-mime-type": "^1.0.2", "stream-mime-type": "^1.0.2",
"try-to-catch": "^3.0.1", "try-to-catch": "^3.0.1",
"uqr": "^0.1.2", "uqr": "^0.1.2",
@ -1075,11 +1075,10 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.19.76", "version": "18.19.75",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.76.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.75.tgz",
"integrity": "sha512-yvR7Q9LdPz2vGpmpJX5LolrgRdWvB67MJKDPSgIIzpFbaf9a1j/f5DnLp5VDyHGMR0QZHlTr1afsD87QCXFHKw==", "integrity": "sha512-UIksWtThob6ZVSyxcOqCLOUNg/dyO1Qvx4McgeuhrEtHTLFTf7BBhEazaE4K806FGTPtzd/2sE90qn4fVr7cyw==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
@ -1413,13 +1412,12 @@
} }
}, },
"node_modules/cloudstorm": { "node_modules/cloudstorm": {
"version": "0.11.4", "version": "0.11.2",
"resolved": "https://registry.npmjs.org/cloudstorm/-/cloudstorm-0.11.4.tgz", "resolved": "https://registry.npmjs.org/cloudstorm/-/cloudstorm-0.11.2.tgz",
"integrity": "sha512-fk0tAyZmUBWrxELyXaKh19s1RJucmhmvTMfB/LrvdRHdUvc20VkD7qCrFaQHSQ/+kzwhSHVY43zNAjtz93pH9A==", "integrity": "sha512-LuKey+nTp5fEGH5TdCxCUWSG1VMcXKV57rsFvGi/XLpdPT1LUTlc5TmCONAaKzy2uZFJm9EG+iIB2Vq+uBqgog==",
"license": "MIT",
"dependencies": { "dependencies": {
"discord-api-types": "^0.37.119", "discord-api-types": "^0.37.119",
"snowtransfer": "^0.12.0" "snowtransfer": "^0.11.0"
}, },
"engines": { "engines": {
"node": ">=16.15.0" "node": ">=16.15.0"
@ -1870,9 +1868,9 @@
} }
}, },
"node_modules/heatsync": { "node_modules/heatsync": {
"version": "2.7.2", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/heatsync/-/heatsync-2.7.2.tgz", "resolved": "https://registry.npmjs.org/heatsync/-/heatsync-2.7.0.tgz",
"integrity": "sha512-1djRg4eufv5q+CRy5SuZSiV3j53KIDSGkDubJB+vXY1OE+AnTkw5HIJxi+0vEjHjX+wbH5syYQunQ/ElAgoEmg==", "integrity": "sha512-9ILOyyHFZKfIrqBmNz+fwKd+zupFE2UqFZ9k4FjRcMjNDp7GtW+K9n2htXLy3CwdDTRd6NV6BPxKvU51UqKIJA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"backtracker": "^4.0.0" "backtracker": "^4.0.0"
@ -2681,10 +2679,9 @@
} }
}, },
"node_modules/snowtransfer": { "node_modules/snowtransfer": {
"version": "0.12.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.12.0.tgz", "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.11.0.tgz",
"integrity": "sha512-EmVTAeSXtA7ZlTqwmZxe5JwRTm4FOXEOqMOzGu8fdVSoqXjcWgQ8IfaIRu/54FamOMjOmcxnpTyNPj5MUqWxpA==", "integrity": "sha512-07rvRnCtXdL/E3PmKTS/zHVlIIIWizKh7YzsUxN2bmX1Fr5odFgZ08J0/dE1YL6XmsbpmEB2r4LBAfdCGzKs7w==",
"license": "MIT",
"dependencies": { "dependencies": {
"discord-api-types": "^0.37.119" "discord-api-types": "^0.37.119"
}, },
@ -3321,10 +3318,9 @@
} }
}, },
"node_modules/zod": { "node_modules/zod": {
"version": "3.24.2", "version": "3.24.1",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz",
"integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==",
"license": "MIT",
"funding": { "funding": {
"url": "https://github.com/sponsors/colinhacks" "url": "https://github.com/sponsors/colinhacks"
} }

View file

@ -40,12 +40,12 @@
"get-relative-path": "^1.0.2", "get-relative-path": "^1.0.2",
"get-stream": "^6.0.1", "get-stream": "^6.0.1",
"h3": "^1.12.0", "h3": "^1.12.0",
"heatsync": "^2.7.2", "heatsync": "^2.7.0",
"lru-cache": "^10.4.3", "lru-cache": "^10.4.3",
"minimist": "^1.2.8", "minimist": "^1.2.8",
"prettier-bytes": "^1.0.4", "prettier-bytes": "^1.0.4",
"sharp": "^0.33.4", "sharp": "^0.33.4",
"snowtransfer": "^0.12.0", "snowtransfer": "^0.11.0",
"stream-mime-type": "^1.0.2", "stream-mime-type": "^1.0.2",
"try-to-catch": "^3.0.1", "try-to-catch": "^3.0.1",
"uqr": "^0.1.2", "uqr": "^0.1.2",

View file

@ -38,7 +38,7 @@ const guildPresenceSetting = new class {
} }
} }
class Presence extends sync.reloadClassMethods(() => Presence) { class Presence extends sync.ReloadableClass {
/** @type {string} */ userID /** @type {string} */ userID
/** @type {{presence: "online" | "offline" | "unavailable", status_msg?: string}} */ data /** @type {{presence: "online" | "offline" | "unavailable", status_msg?: string}} */ data
/** @private @type {?string | undefined} */ mxid /** @private @type {?string | undefined} */ mxid
@ -70,6 +70,7 @@ class Presence extends sync.reloadClassMethods(() => Presence) {
}, this.delay * presenceLoopInterval).unref() }, this.delay * presenceLoopInterval).unref()
} }
} }
sync.reloadClassMethods(Presence)
const presenceTracker = new class { const presenceTracker = new class {
/** @private @type {Map<string, Presence>} userID -> Presence */ presences = sync.remember(() => new Map()) /** @private @type {Map<string, Presence>} userID -> Presence */ presences = sync.remember(() => new Map())

View file

@ -39,14 +39,7 @@ function render(event, filename, locals) {
defaultContentType(event, "text/html; charset=utf-8") defaultContentType(event, "text/html; charset=utf-8")
const session = await auth.useSession(event) const session = await auth.useSession(event)
const managed = await auth.getManagedGuilds(event) const managed = await auth.getManagedGuilds(event)
const rel = (to, paramsObject) => { const rel = x => getRelativePath(event.path, x)
let result = getRelativePath(event.path, to)
if (paramsObject) {
const params = new URLSearchParams(paramsObject)
result += "?" + params.toString()
}
return result
}
return template(Object.assign({}, return template(Object.assign({},
getQuery(event), // Query parameters can be easily accessed on the top level but don't allow them to overwrite anything getQuery(event), // Query parameters can be easily accessed on the top level but don't allow them to overwrite anything
globals, // Globals globals, // Globals

View file

@ -18,10 +18,8 @@ block body
div div
!= icons.Icons.IconInfo != icons.Icons.IconInfo
div div
- const self = `@${reg.sender_localpart}:${reg.ooye.server_name}`
strong You picked self-service mode 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 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 h3.mt32.fs-category Choose a space
@ -35,12 +33,13 @@ block body
else else
if session.data.mxid if session.data.mxid
tr 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 else
tr tr
td.d-flex.ai-center.pl16.g16 td.d-flex.ai-center.pl16.g16
| You need to log in with Matrix first. | 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 h3.mt48.fs-category Auto-create
.s-card .s-card

View file

@ -7,8 +7,6 @@ block body
.d-flex.g16#form-container .d-flex.g16#form-container
.fl-grow1 .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") 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 .d-flex.gy4.fd-column
label.s-label(for="mxid") Your Matrix ID label.s-label(for="mxid") Your Matrix ID
input.fl-grow1.s-input.wmx3#mxid(name="mxid" required placeholder="@user:example.org") input.fl-grow1.s-input.wmx3#mxid(name="mxid" required placeholder="@user:example.org")

View file

@ -17,12 +17,10 @@ const auth = sync.require("../auth")
const schema = { const schema = {
form: z.object({ form: z.object({
mxid: z.string(), mxid: z.string()
next: z.string().optional()
}), }),
token: z.object({ token: z.object({
token: z.string().optional(), token: z.string()
next: z.string().optional()
}) })
} }
@ -45,16 +43,17 @@ const validToken = new LRUCache({max: 200})
*/ */
as.router.get("/log-in-with-matrix", defineEventHandler(async event => { 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 // 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") const userAgent = getRequestHeader(event, "User-Agent")
if (userAgent?.match(/bot/)) throw createError({status: 400, data: "Sorry URL previewer, you can't have this URL."}) 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) if (!validToken.has(token)) return sendRedirect(event, `${reg.ooye.bridge_origin}/log-in-with-matrix`, 302)
const session = await auth.useSession(event) const session = await auth.useSession(event)
@ -64,13 +63,12 @@ as.router.get("/log-in-with-matrix", defineEventHandler(async event => {
await session.update({mxid}) await session.update({mxid})
if (!next) next = "./" // open to homepage where they can see they're logged in return sendRedirect(event, "./", 302) // open to homepage where they can see they're logged in
return sendRedirect(event, next, 302)
})) }))
as.router.post("/api/log-in-with-matrix", defineEventHandler(async event => { as.router.post("/api/log-in-with-matrix", defineEventHandler(async event => {
const api = getAPI(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 let roomID = null
// Don't extend a duplicate invite for the same user // 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) validToken.set(token, mxid)
console.log(`web log in requested for ${mxid}`) console.log(`web log in requested for ${mxid}`)
const paramsObject = {token} 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.`
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.`
await api.sendEvent(roomID, "m.room.message", { await api.sendEvent(roomID, "m.room.message", {
msgtype: "m.text", msgtype: "m.text",
body body