diff --git a/src/m2d/event-dispatcher.js b/src/m2d/event-dispatcher.js index 48bff11..eb1fba0 100644 --- a/src/m2d/event-dispatcher.js +++ b/src/m2d/event-dispatcher.js @@ -357,7 +357,15 @@ async event => { await api.ackEvent(event) })) - +function getFromInviteRoomState(inviteRoomState, nskey, key) { + if (!Array.isArray(inviteRoomState)) return null + for (const event of inviteRoomState) { + if (event.type === nskey && event.state_key === "") { + return event.content[key] + } + } + return null +} sync.addTemporaryListener(as, "type:m.space.child", guard("m.space.child", /** @@ -390,16 +398,24 @@ async event => { } // We were invited to a room. We should join, and register the invite details for future reference in web. - try { - var inviteRoomState = await api.getInviteState(event.room_id, event) - } catch (e) { - console.error(e) - return await api.leaveRoomWithReason(event.room_id, `I wasn't able to find out what this room is. Please report this as a bug. Check console for more details. (${e.toString()})`) + let attemptedApiMessage = "According to unsigned invite data." + let inviteRoomState = event.unsigned?.invite_room_state + if (!Array.isArray(inviteRoomState) || inviteRoomState.length === 0) { + try { + inviteRoomState = await api.getInviteState(event.room_id) + attemptedApiMessage = "According to SSS API." + } catch (e) { + attemptedApiMessage = "According to unsigned invite data. SSS API unavailable: " + e.toString() + } } - if (!inviteRoomState?.name) return await api.leaveRoomWithReason(event.room_id, `Please only invite me to rooms that have a name/avatar set. Update the room details and reinvite.`) + const name = getFromInviteRoomState(inviteRoomState, "m.room.name", "name") + const topic = getFromInviteRoomState(inviteRoomState, "m.room.topic", "topic") + const avatar = getFromInviteRoomState(inviteRoomState, "m.room.avatar", "url") + const creationType = getFromInviteRoomState(inviteRoomState, "m.room.create", "type") + if (!name) return await api.leaveRoomWithReason(event.room_id, `Please only invite me to rooms that have a name/avatar set. Update the room details and reinvite! (${attemptedApiMessage})`) await api.joinRoom(event.room_id) - db.prepare("INSERT OR IGNORE INTO invite (mxid, room_id, type, name, topic, avatar) VALUES (?, ?, ?, ?, ?, ?)").run(event.sender, event.room_id, inviteRoomState.type, inviteRoomState.name, inviteRoomState.topic, inviteRoomState.avatar) - if (inviteRoomState.avatar) utils.getPublicUrlForMxc(inviteRoomState.avatar) // make sure it's available in the media_proxy allowed URLs + db.prepare("INSERT OR IGNORE INTO invite (mxid, room_id, type, name, topic, avatar) VALUES (?, ?, ?, ?, ?, ?)").run(event.sender, event.room_id, creationType, name, topic, avatar) + if (avatar) utils.getPublicUrlForMxc(avatar) // make sure it's available in the media_proxy allowed URLs } if (utils.eventSenderIsFromDiscord(event.state_key)) return diff --git a/src/matrix/api.js b/src/matrix/api.js index 7e503c2..b71c068 100644 --- a/src/matrix/api.js +++ b/src/matrix/api.js @@ -158,82 +158,20 @@ function getStateEventOuter(roomID, type, key) { /** * @param {string} roomID - * @param {{unsigned?: {invite_room_state?: Ty.Event.InviteStrippedState[]}}} [event] - * @returns {Promise<{name: string?, topic: string?, avatar: string?, type: string?}>} + * @returns {Promise} */ -async function getInviteState(roomID, event) { - function getFromInviteRoomState(strippedState, nskey, key) { - if (!Array.isArray(strippedState)) return null - for (const event of strippedState) { - if (event.type === nskey && event.state_key === "") { - return event.content[key] +async function getInviteState(roomID) { + /** @type {Ty.R.SSS} */ + const root = await mreq.mreq("POST", path("/client/unstable/org.matrix.simplified_msc3575/sync", `@${reg.sender_localpart}:${reg.ooye.server_name}`, {timeout: "0"}), { + room_subscriptions: { + [roomID]: { + timeline_limit: 0, + required_state: [] } } - return null - } - - // Try extracting from event (if passed) - if (Array.isArray(event?.unsigned?.invite_room_state) && event.unsigned.invite_room_state.length) { - return { - name: getFromInviteRoomState(event.unsigned.invite_room_state, "m.room.name", "name"), - topic: getFromInviteRoomState(event.unsigned.invite_room_state, "m.room.topic", "topic"), - avatar: getFromInviteRoomState(event.unsigned.invite_room_state, "m.room.avatar", "url"), - type: getFromInviteRoomState(event.unsigned.invite_room_state, "m.room.create", "type") - } - } - - // Try calling sliding sync API and extracting from stripped state - try { - /** @type {Ty.R.SSS} */ - var root = await mreq.mreq("POST", path("/client/unstable/org.matrix.simplified_msc3575/sync", `@${reg.sender_localpart}:${reg.ooye.server_name}`, {timeout: "0"}), { - lists: { - a: { - ranges: [[0, 999]], - timeline_limit: 0, - required_state: [], - filters: { - is_invite: true - } - } - } - }) - - // Extract from sliding sync response if valid (seems to be okay on Synapse, Tuwunel and Continuwuity at time of writing) - if ("lists" in root) { - if (!root.rooms?.[roomID]) { - const e = new Error("Room data unavailable via SSS") - e["data_sss"] = root - throw e - } - - const roomResponse = root.rooms[roomID] - const strippedState = "stripped_state" in roomResponse ? roomResponse.stripped_state : roomResponse.invite_state - - return { - name: getFromInviteRoomState(strippedState, "m.room.name", "name"), - topic: getFromInviteRoomState(strippedState, "m.room.topic", "topic"), - avatar: getFromInviteRoomState(strippedState, "m.room.avatar", "url"), - type: getFromInviteRoomState(strippedState, "m.room.create", "type") - } - } - } catch (e) {} - - // Invalid sliding sync response, try alternative (required for Conduit at time of writing) - const hierarchy = await getHierarchy(roomID, {limit: 1}) - if (hierarchy?.rooms?.[0]?.room_id === roomID) { - const room = hierarchy?.rooms?.[0] - return { - name: room.name ?? null, - topic: room.topic ?? null, - avatar: room.avatar_url ?? null, - type: room.room_type - } - } - - const e = new Error("Room data unavailable via SSS/hierarchy") - e["data_sss"] = root - e["data_hierarchy"] = hierarchy - throw e + }) + const roomResponse = root.rooms[roomID] + return "stripped_state" in roomResponse ? roomResponse.stripped_state : roomResponse.invite_state } /** diff --git a/src/matrix/kstate.js b/src/matrix/kstate.js index 3648f2d..c901ce1 100644 --- a/src/matrix/kstate.js +++ b/src/matrix/kstate.js @@ -149,10 +149,8 @@ async function roomToKState(roomID, limitToEvents) { } else { const root = [] await Promise.all(limitToEvents.map(async ([type, key]) => { - try { - const outer = await api.getStateEventOuter(roomID, type, key) - root.push(outer) - } catch (e) {} + const outer = await api.getStateEventOuter(roomID, type, key) + root.push(outer) })) return stateToKState(root) } diff --git a/src/matrix/mreq.js b/src/matrix/mreq.js index bb59506..9085add 100644 --- a/src/matrix/mreq.js +++ b/src/matrix/mreq.js @@ -77,7 +77,6 @@ async function mreq(method, url, bodyIn, extra = {}) { /** @type {any} */ var root = JSON.parse(text) } catch (e) { - delete opts.headers?.["Authorization"] throw new MatrixServerError(text, {baseUrl, url, ...opts}) } diff --git a/src/types.d.ts b/src/types.d.ts index 6ee2eb1..951d93c 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -433,7 +433,6 @@ export namespace R { guest_can_join: boolean join_rule?: string name?: string - topic?: string num_joined_members: number room_id: string room_type?: string