Compare commits
6 commits
16309f26b3
...
10d14bbdaa
| Author | SHA1 | Date | |
|---|---|---|---|
| 10d14bbdaa | |||
| 677d899a92 | |||
| 9492137ca6 | |||
| 6aa2bfad13 | |||
| fc8d400b7d | |||
| f1313db028 |
6 changed files with 17 additions and 108 deletions
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es2024",
|
|
||||||
"module": "nodenext",
|
|
||||||
"strict": true,
|
|
||||||
"noImplicitAny": false,
|
|
||||||
"useUnknownInCatchVariables": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -207,7 +207,6 @@ async function attachmentToEvent(mentions, attachment) {
|
||||||
* - alwaysReturnFormattedBody: false - formatted_body will be skipped if it is the same as body because the message is plaintext. if you want the formatted_body to be returned anyway, for example to merge it with another message, then set this to true.
|
* - alwaysReturnFormattedBody: false - formatted_body will be skipped if it is the same as body because the message is plaintext. if you want the formatted_body to be returned anyway, for example to merge it with another message, then set this to true.
|
||||||
* - scanTextForMentions: true - needs to be set to false when converting forwarded messages etc which may be from a different channel that can't be scanned.
|
* - scanTextForMentions: true - needs to be set to false when converting forwarded messages etc which may be from a different channel that can't be scanned.
|
||||||
* @param {{api: import("../../matrix/api"), snow?: import("snowtransfer").SnowTransfer}} di simple-as-nails dependency injection for the matrix API
|
* @param {{api: import("../../matrix/api"), snow?: import("snowtransfer").SnowTransfer}} di simple-as-nails dependency injection for the matrix API
|
||||||
* @returns {Promise<{$type: string, $sender?: string, [x: string]: any}[]>}
|
|
||||||
*/
|
*/
|
||||||
async function messageToEvent(message, guild, options = {}, di) {
|
async function messageToEvent(message, guild, options = {}, di) {
|
||||||
const events = []
|
const events = []
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,7 @@ function path(p, mxid, otherParams = {}) {
|
||||||
const u = new URL(p, "http://localhost")
|
const u = new URL(p, "http://localhost")
|
||||||
if (mxid) u.searchParams.set("user_id", mxid)
|
if (mxid) u.searchParams.set("user_id", mxid)
|
||||||
for (const entry of Object.entries(otherParams)) {
|
for (const entry of Object.entries(otherParams)) {
|
||||||
if (Array.isArray(entry[1])) {
|
if (entry[1] != undefined) {
|
||||||
for (const element of entry[1]) {
|
|
||||||
u.searchParams.append(entry[0], element)
|
|
||||||
}
|
|
||||||
} else if (entry[1] != undefined) {
|
|
||||||
u.searchParams.set(entry[0], entry[1])
|
u.searchParams.set(entry[0], entry[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -66,14 +62,11 @@ async function createRoom(content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} roomIDOrAlias
|
|
||||||
* @param {string?} [mxid]
|
|
||||||
* @param {string[]?} [via]
|
|
||||||
* @returns {Promise<string>} room ID
|
* @returns {Promise<string>} room ID
|
||||||
*/
|
*/
|
||||||
async function joinRoom(roomIDOrAlias, mxid, via) {
|
async function joinRoom(roomIDOrAlias, mxid) {
|
||||||
/** @type {Ty.R.RoomJoined} */
|
/** @type {Ty.R.RoomJoined} */
|
||||||
const root = await mreq.mreq("POST", path(`/client/v3/join/${roomIDOrAlias}`, mxid, {via}), {})
|
const root = await mreq.mreq("POST", path(`/client/v3/join/${roomIDOrAlias}`, mxid), {})
|
||||||
return root.room_id
|
return root.room_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
src/types.d.ts
vendored
10
src/types.d.ts
vendored
|
|
@ -149,14 +149,6 @@ export namespace Event {
|
||||||
prev_content?: any
|
prev_content?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StrippedChildStateEvent = {
|
|
||||||
type: string
|
|
||||||
state_key: string
|
|
||||||
sender: string
|
|
||||||
origin_server_ts: number
|
|
||||||
content: any
|
|
||||||
}
|
|
||||||
|
|
||||||
export type M_Room_Message = {
|
export type M_Room_Message = {
|
||||||
msgtype: "m.text" | "m.emote"
|
msgtype: "m.text" | "m.emote"
|
||||||
body: string
|
body: string
|
||||||
|
|
@ -353,7 +345,7 @@ export namespace R {
|
||||||
export type Hierarchy = {
|
export type Hierarchy = {
|
||||||
avatar_url?: string
|
avatar_url?: string
|
||||||
canonical_alias?: string
|
canonical_alias?: string
|
||||||
children_state: Event.StrippedChildStateEvent[]
|
children_state: {}
|
||||||
guest_can_join: boolean
|
guest_can_join: boolean
|
||||||
join_rule?: string
|
join_rule?: string
|
||||||
name?: string
|
name?: string
|
||||||
|
|
|
||||||
|
|
@ -133,15 +133,11 @@ as.router.post("/api/link-space", defineEventHandler(async event => {
|
||||||
const existing = select("guild_space", "guild_id", {}, "WHERE guild_id = ? OR space_id = ?").get(guildID, spaceID)
|
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`})
|
if (existing) throw createError({status: 400, message: "Bad Request", data: `Guild ID ${guildID} or space ID ${spaceID} are already bridged and cannot be reused`})
|
||||||
|
|
||||||
const inviteSender = select("invite", "mxid", {mxid: session.data.mxid, room_id: spaceID}).pluck().get()
|
|
||||||
const inviteSenderServer = inviteSender?.match(/:(.*)/)?.[1]
|
|
||||||
const via = [inviteSenderServer || ""]
|
|
||||||
|
|
||||||
// Check space exists and bridge is joined
|
// Check space exists and bridge is joined
|
||||||
try {
|
try {
|
||||||
await api.joinRoom(parsedBody.space_id, null, via)
|
await api.joinRoom(parsedBody.space_id)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw createError({status: 400, message: "Unable To Join", data: `Unable to join the requested Matrix space. Please invite the bridge to the space and try again. (Server said: ${e.errcode} - ${e.message})`})
|
throw createError({status: 403, message: e.errcode, data: `${e.errcode} - ${e.message}`})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check bridge has PL 100
|
// Check bridge has PL 100
|
||||||
|
|
@ -189,33 +185,19 @@ as.router.post("/api/link", defineEventHandler(async event => {
|
||||||
if (row) throw createError({status: 400, message: "Bad Request", data: `Channel ID ${row.channel_id} or room ID ${parsedBody.matrix} are already bridged and cannot be reused`})
|
if (row) throw createError({status: 400, message: "Bad Request", data: `Channel ID ${row.channel_id} or room ID ${parsedBody.matrix} are already bridged and cannot be reused`})
|
||||||
|
|
||||||
// Check room is part of the guild's space
|
// Check room is part of the guild's space
|
||||||
let foundRoom = false
|
let found = false
|
||||||
/** @type {string[]?} */
|
|
||||||
let foundVia = null
|
|
||||||
for await (const room of api.generateFullHierarchy(spaceID)) {
|
for await (const room of api.generateFullHierarchy(spaceID)) {
|
||||||
// When finding a space during iteration, look at space's children state, because we need a `via` to join the room (when we find it later)
|
|
||||||
for (const state of room.children_state) {
|
|
||||||
if (state.type === "m.space.child" && state.state_key === parsedBody.matrix) {
|
|
||||||
foundVia = state.content.via
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// When finding a room during iteration, see if it was the requested room (to confirm that the room is in the space)
|
|
||||||
if (room.room_id === parsedBody.matrix && !room.room_type) {
|
if (room.room_id === parsedBody.matrix && !room.room_type) {
|
||||||
foundRoom = true
|
found = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foundRoom && foundVia) break
|
|
||||||
}
|
}
|
||||||
if (!foundRoom) throw createError({status: 400, message: "Bad Request", data: "Matrix room needs to be part of the bridged space"})
|
if (!found) throw createError({status: 400, message: "Bad Request", data: "Matrix room needs to be part of the bridged space"})
|
||||||
|
|
||||||
// Check room exists and bridge is joined
|
// Check room exists and bridge is joined
|
||||||
try {
|
try {
|
||||||
await api.joinRoom(parsedBody.matrix, null, foundVia)
|
await api.joinRoom(parsedBody.matrix)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!foundVia) {
|
|
||||||
throw createError({status: 400, message: "Unable To Join", data: `Unable to join the requested Matrix room. Please invite the bridge to the room and try again. (Server said: ${e.errcode} - ${e.message})`})
|
|
||||||
}
|
|
||||||
throw createError({status: 403, message: e.errcode, data: `${e.errcode} - ${e.message}`})
|
throw createError({status: 403, message: e.errcode, data: `${e.errcode} - ${e.message}`})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ test("web link space: check that OOYE is joined", async t => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
t.equal(error.data, "Unable to join the requested Matrix space. Please invite the bridge to the space and try again. (Server said: M_FORBIDDEN - not allowed to join I guess)")
|
t.equal(error.data, "M_FORBIDDEN - not allowed to join I guess")
|
||||||
t.equal(called, 1)
|
t.equal(called, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -360,7 +360,7 @@ test("web link room: check that room is part of space (not in hierarchy)", async
|
||||||
t.equal(called, 1)
|
t.equal(called, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("web link room: check that bridge can join room (notices lack of via and asks for invite instead)", async t => {
|
test("web link room: check that bridge can join room", async t => {
|
||||||
let called = 0
|
let called = 0
|
||||||
const [error] = await tryToCatch(() => router.test("post", "/api/link", {
|
const [error] = await tryToCatch(() => router.test("post", "/api/link", {
|
||||||
sessionData: {
|
sessionData: {
|
||||||
|
|
@ -381,55 +381,7 @@ test("web link room: check that bridge can join room (notices lack of via and as
|
||||||
t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
|
t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
|
||||||
yield {
|
yield {
|
||||||
room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
||||||
children_state: [],
|
children_state: {},
|
||||||
guest_can_join: false,
|
|
||||||
num_joined_members: 2
|
|
||||||
}
|
|
||||||
/* c8 ignore next */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
t.equal(error.data, "Unable to join the requested Matrix room. Please invite the bridge to the room and try again. (Server said: M_FORBIDDEN - not allowed to join I guess)")
|
|
||||||
t.equal(called, 2)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("web link room: check that bridge can join room (uses via for join attempt)", async t => {
|
|
||||||
let called = 0
|
|
||||||
const [error] = await tryToCatch(() => router.test("post", "/api/link", {
|
|
||||||
sessionData: {
|
|
||||||
managedGuilds: ["665289423482519565"]
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
discord: "665310973967597573",
|
|
||||||
matrix: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
|
||||||
guild_id: "665289423482519565"
|
|
||||||
},
|
|
||||||
api: {
|
|
||||||
async joinRoom(roomID, _, via) {
|
|
||||||
called++
|
|
||||||
t.deepEqual(via, ["cadence.moe", "hashi.re"])
|
|
||||||
throw new MatrixServerError({errcode: "M_FORBIDDEN", error: "not allowed to join I guess"})
|
|
||||||
},
|
|
||||||
async *generateFullHierarchy(spaceID) {
|
|
||||||
called++
|
|
||||||
t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
|
|
||||||
yield {
|
|
||||||
room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
|
||||||
children_state: [],
|
|
||||||
guest_can_join: false,
|
|
||||||
num_joined_members: 2
|
|
||||||
}
|
|
||||||
yield {
|
|
||||||
room_id: "!zTMspHVUBhFLLSdmnS:cadence.moe",
|
|
||||||
children_state: [{
|
|
||||||
type: "m.space.child",
|
|
||||||
state_key: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
|
||||||
sender: "@elliu:hashi.re",
|
|
||||||
content: {
|
|
||||||
via: ["cadence.moe", "hashi.re"]
|
|
||||||
},
|
|
||||||
origin_server_ts: 0
|
|
||||||
}],
|
|
||||||
guest_can_join: false,
|
guest_can_join: false,
|
||||||
num_joined_members: 2
|
num_joined_members: 2
|
||||||
}
|
}
|
||||||
|
|
@ -462,7 +414,7 @@ test("web link room: check that bridge has PL 100 in target room (event missing)
|
||||||
t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
|
t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
|
||||||
yield {
|
yield {
|
||||||
room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
||||||
children_state: [],
|
children_state: {},
|
||||||
guest_can_join: false,
|
guest_can_join: false,
|
||||||
num_joined_members: 2
|
num_joined_members: 2
|
||||||
}
|
}
|
||||||
|
|
@ -502,7 +454,7 @@ test("web link room: check that bridge has PL 100 in target room (users default)
|
||||||
t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
|
t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
|
||||||
yield {
|
yield {
|
||||||
room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
||||||
children_state: [],
|
children_state: {},
|
||||||
guest_can_join: false,
|
guest_can_join: false,
|
||||||
num_joined_members: 2
|
num_joined_members: 2
|
||||||
}
|
}
|
||||||
|
|
@ -542,7 +494,7 @@ test("web link room: successfully calls createRoom", async t => {
|
||||||
t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
|
t.equal(spaceID, "!zTMspHVUBhFLLSdmnS:cadence.moe")
|
||||||
yield {
|
yield {
|
||||||
room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
room_id: "!NDbIqNpJyPvfKRnNcr:cadence.moe",
|
||||||
children_state: [],
|
children_state: {},
|
||||||
guest_can_join: false,
|
guest_can_join: false,
|
||||||
num_joined_members: 2
|
num_joined_members: 2
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue