diff --git a/src/m2d/converters/event-to-message.js b/src/m2d/converters/event-to-message.js index ed8d2c3..2add279 100644 --- a/src/m2d/converters/event-to-message.js +++ b/src/m2d/converters/event-to-message.js @@ -844,7 +844,6 @@ async function eventToMessage(event, guild, channel, di) { // The matrix spec hasn't decided whether \n counts as a newline or not, but I'm going to count it, because if it's in the data it's there for a reason. // But I should not count it if it's between block elements. input = input.replace(/(<\/?([^ >]+)[^>]*>)?\n(<\/?([^ >]+)[^>]*>)?/g, (whole, beforeContext, beforeTag, afterContext, afterTag) => { - // console.error(beforeContext, beforeTag, afterContext, afterTag) if (typeof beforeTag !== "string" && typeof afterTag !== "string") { return "
" } diff --git a/src/web/routes/guild.js b/src/web/routes/guild.js index 5f9e2d9..dfb393b 100644 --- a/src/web/routes/guild.js +++ b/src/web/routes/guild.js @@ -133,6 +133,20 @@ function getChannelRoomsLinks(guild, rooms, roles) { } } +/** + * @param {string} mxid + */ +function getInviteTargetSpaces(mxid) { + /** @type {{room_id: string, mxid: string, type: string, name: string, topic: string?, avatar: string?}[]} */ + const spaces = + // invited spaces + db.prepare("SELECT room_id, invite.mxid, type, name, topic, avatar FROM invite LEFT JOIN guild_space ON invite.room_id = guild_space.space_id WHERE mxid = ? AND space_id IS NULL AND type = 'm.space'").all(mxid) + // moderated spaces + .concat(db.prepare("SELECT room_id, invite.mxid, type, name, topic, avatar FROM invite LEFT JOIN guild_space ON invite.room_id = guild_space.space_id INNER JOIN member_cache USING (room_id) WHERE member_cache.mxid = ? AND power_level >= 50 AND space_id IS NULL AND type = 'm.space'").all(mxid)) + const seen = new Set(spaces.map(s => s.room_id)) + return spaces.filter(s => seen.delete(s.room_id)) +} + as.router.get("/guild", defineEventHandler(async event => { const {guild_id} = await getValidatedQuery(event, schema.guild.parse) const session = await auth.useSession(event) @@ -148,13 +162,7 @@ as.router.get("/guild", defineEventHandler(async event => { // Self-service guild that hasn't been linked yet - needs a special page encouraging the link flow if (!row.space_id && row.autocreate === 0) { - let spaces = - // invited spaces - db.prepare("SELECT room_id, type, name, topic, avatar FROM invite LEFT JOIN guild_space ON invite.room_id = guild_space.space_id WHERE mxid = ? AND space_id IS NULL AND type = 'm.space'").all(session.data.mxid) - // moderated spaces - .concat(db.prepare("SELECT room_id, type, name, topic, avatar FROM invite LEFT JOIN guild_space ON invite.room_id = guild_space.space_id INNER JOIN member_cache USING (room_id) WHERE member_cache.mxid = ? AND power_level >= 50 AND space_id IS NULL AND type = 'm.space'").all(session.data.mxid)) - const seen = new Set(spaces.map(s => s.room_id)) - spaces = spaces.filter(s => seen.delete(s.room_id)) + const spaces = session.data.mxid ? getInviteTargetSpaces(session.data.mxid) : [] return pugSync.render(event, "guild_not_linked.pug", {guild, guild_id, spaces}) } @@ -257,3 +265,4 @@ as.router.post("/api/invite", defineEventHandler(async event => { })) module.exports._getPosition = getPosition +module.exports.getInviteTargetSpaces = getInviteTargetSpaces diff --git a/src/web/routes/link.js b/src/web/routes/link.js index 248b4ef..43995fc 100644 --- a/src/web/routes/link.js +++ b/src/web/routes/link.js @@ -11,6 +11,8 @@ const {discord, db, as, sync, select, from} = require("../../passthrough") const auth = sync.require("../auth") /** @type {import("../../matrix/utils")}*/ const utils = sync.require("../../matrix/utils") +/** @type {import("./guild")}*/ +const guildRoute = sync.require("./guild") /** * @param {H3Event} event @@ -107,13 +109,15 @@ as.router.post("/api/link-space", defineEventHandler(async event => { // Check space ID if (!session.data.mxid) throw createError({status: 403, message: "Forbidden", data: "Can't link with your Matrix space if you aren't logged in to Matrix"}) const spaceID = parsedBody.space_id - const inviteRow = select("invite", ["mxid", "type"], {mxid: session.data.mxid, room_id: spaceID}).get() - if (!inviteRow || inviteRow.type !== "m.space") throw createError({status: 403, message: "Forbidden", data: "You personally must invite OOYE to that space on Matrix"}) // Check they are not already bridged const existing = select("guild_space", "guild_id", {}, "WHERE guild_id = ? OR space_id = ?").get(guildID, spaceID) if (existing) throw createError({status: 400, message: "Bad Request", data: `Guild ID ${guildID} or space ID ${spaceID} are already bridged and cannot be reused`}) + // Check space ID is a valid invite target + const inviteRow = guildRoute.getInviteTargetSpaces(session.data.mxid).find(s => s.room_id === spaceID) + if (!inviteRow) throw createError({status: 403, message: "Forbidden", data: "You personally must invite OOYE to that space on Matrix"}) + const inviteServer = inviteRow.mxid.match(/:(.*)/)?.[1] assert(inviteServer) const via = [inviteServer]