Compare commits
2 commits
da5525a542
...
4167a01ed1
Author | SHA1 | Date | |
---|---|---|---|
4167a01ed1 | |||
c127923f4d |
5 changed files with 143 additions and 5 deletions
|
@ -1014,3 +1014,15 @@ test("message2event: @everyone within a link", async t => {
|
||||||
"m.mentions": {}
|
"m.mentions": {}
|
||||||
}])
|
}])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("message2event: forwarded image", async t => {
|
||||||
|
const events = await messageToEvent(data.message.forwarded_image)
|
||||||
|
t.deepEqual(events, [{
|
||||||
|
$type: "m.room.message",
|
||||||
|
msgtype: "m.text",
|
||||||
|
body: "https://github.com/@everyone",
|
||||||
|
format: "org.matrix.custom.html",
|
||||||
|
formatted_body: `<a href="https://github.com/@everyone">https://github.com/@everyone</a>`,
|
||||||
|
"m.mentions": {}
|
||||||
|
}])
|
||||||
|
})
|
||||||
|
|
|
@ -205,7 +205,7 @@ block body
|
||||||
p.s-description All of the above, and publicly visible in the Matrix space directory (like Server Discovery)
|
p.s-description All of the above, and publicly visible in the Matrix space directory (like Server Discovery)
|
||||||
|
|
||||||
h3.mt32.fs-category Manually link channels
|
h3.mt32.fs-category Manually link channels
|
||||||
form.d-flex.g16.ai-start(method="post" action="/api/link")
|
form.d-flex.g16.ai-start(hx-post="/api/privacy-level" hx-trigger="submit" hx-disabled-elt="this")
|
||||||
.fl-grow2.s-btn-group.fd-column.w40
|
.fl-grow2.s-btn-group.fd-column.w40
|
||||||
each channel in unlinkedChannels
|
each channel in unlinkedChannels
|
||||||
input.s-btn--radio(type="radio" name="discord" id=channel.id value=channel.id)
|
input.s-btn--radio(type="radio" name="discord" id=channel.id value=channel.id)
|
||||||
|
@ -220,7 +220,8 @@ block body
|
||||||
+matrix(room, true)
|
+matrix(room, true)
|
||||||
else
|
else
|
||||||
.s-empty-state.p8 All Matrix rooms are linked.
|
.s-empty-state.p8 All Matrix rooms are linked.
|
||||||
|
input(type="hidden" name="guild_id" value=guild_id)
|
||||||
div
|
div
|
||||||
button.s-btn.s-btn__icon.s-btn__filled
|
button.s-btn.s-btn__icon.s-btn__filled.htmx-indicator
|
||||||
!= icons.Icons.IconLink
|
!= icons.Icons.IconMerge
|
||||||
= ` Connect`
|
= ` Link`
|
||||||
|
|
63
src/web/routes/link.js
Normal file
63
src/web/routes/link.js
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const {z} = require("zod")
|
||||||
|
const {defineEventHandler, useSession, createError, readValidatedBody} = require("h3")
|
||||||
|
const Ty = require("../../types")
|
||||||
|
|
||||||
|
const {discord, db, as, sync, select, from} = require("../../passthrough")
|
||||||
|
/** @type {import("../../d2m/actions/create-space")} */
|
||||||
|
const createSpace = sync.require("../../d2m/actions/create-space")
|
||||||
|
/** @type {import("../../d2m/actions/create-room")} */
|
||||||
|
const createRoom = sync.require("../../d2m/actions/create-room")
|
||||||
|
const {reg} = require("../../matrix/read-registration")
|
||||||
|
|
||||||
|
/** @type {import("../../matrix/api")} */
|
||||||
|
const api = sync.require("../../matrix/api")
|
||||||
|
|
||||||
|
const schema = {
|
||||||
|
link: z.object({
|
||||||
|
guild_id: z.string(),
|
||||||
|
matrix: z.string(),
|
||||||
|
discord: z.string()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
as.router.post("/api/link", defineEventHandler(async event => {
|
||||||
|
const parsedBody = await readValidatedBody(event, schema.link.parse)
|
||||||
|
const session = await useSession(event, {password: reg.as_token})
|
||||||
|
|
||||||
|
// Check guild ID or nonce
|
||||||
|
const guildID = parsedBody.guild_id
|
||||||
|
if (!(session.data.managedGuilds || []).includes(guildID)) throw createError({status: 403, message: "Forbidden", data: "Can't edit a guild you don't have Manage Server permissions in"})
|
||||||
|
|
||||||
|
// Check guild is bridged
|
||||||
|
const guild = discord.guilds.get(guildID)
|
||||||
|
if (!guild) throw createError({status: 400, message: "Bad Request", data: "Discord guild does not exist or bot has not joined it"})
|
||||||
|
const spaceID = await createSpace.ensureSpace(guild)
|
||||||
|
|
||||||
|
// Check channel exists
|
||||||
|
const channel = discord.channels.get(parsedBody.discord)
|
||||||
|
if (!channel) throw createError({status: 400, message: "Bad Request", data: "Discord channel does not exist"})
|
||||||
|
|
||||||
|
// Check channel and room are not already bridged
|
||||||
|
const row = from("channel_room").select("channel_id", "room_id").and("WHERE channel_id = ? OR room_id = ?").get(parsedBody.discord, parsedBody.matrix)
|
||||||
|
if (row) throw createError({status: 400, message: "Bad Request", data: `Channel ID ${row.channel_id} and room ID ${row.room_id} are already bridged and cannot be reused`})
|
||||||
|
|
||||||
|
// Check room exists and bridge is joined and bridge has PL 100
|
||||||
|
const self = `@${reg.sender_localpart}:${reg.ooye.server_name}`
|
||||||
|
/** @type {Ty.Event.M_Room_Member} */
|
||||||
|
const memberEvent = await api.getStateEvent(parsedBody.matrix, "m.room.member", self)
|
||||||
|
if (memberEvent.membership !== "join") throw createError({status: 400, message: "Bad Request", data: "Matrix room does not exist"})
|
||||||
|
/** @type {Ty.Event.M_Power_Levels} */
|
||||||
|
const powerLevelsStateContent = await api.getStateEvent(parsedBody.matrix, "m.room.power_levels", "")
|
||||||
|
const selfPowerLevel = powerLevelsStateContent.users?.[self] || powerLevelsStateContent.users_default || 0
|
||||||
|
if (selfPowerLevel < (powerLevelsStateContent.state_default || 50) || selfPowerLevel < 100) throw createError({status: 400, message: "Bad Request", data: "OOYE needs power level 100 (admin) in the target Matrix room"})
|
||||||
|
|
||||||
|
// Insert database entry
|
||||||
|
db.prepare("INSERT INTO channel_room (channel_id, room_id, name, guild_id) VALUES (?, ?, ?, ?)").run(parsedBody.discord, parsedBody.matrix, channel.name, guildID)
|
||||||
|
|
||||||
|
// Sync room data and space child
|
||||||
|
createRoom.syncRoom(parsedBody.discord)
|
||||||
|
|
||||||
|
return null // 204
|
||||||
|
}))
|
|
@ -23,8 +23,9 @@ pugSync.createRoute(as.router, "/ok", "ok.pug")
|
||||||
|
|
||||||
sync.require("./routes/download-matrix")
|
sync.require("./routes/download-matrix")
|
||||||
sync.require("./routes/download-discord")
|
sync.require("./routes/download-discord")
|
||||||
sync.require("./routes/invite")
|
|
||||||
sync.require("./routes/guild-settings")
|
sync.require("./routes/guild-settings")
|
||||||
|
sync.require("./routes/invite")
|
||||||
|
sync.require("./routes/link")
|
||||||
sync.require("./routes/oauth")
|
sync.require("./routes/oauth")
|
||||||
sync.require("./routes/qr")
|
sync.require("./routes/qr")
|
||||||
|
|
||||||
|
|
61
test/data.js
61
test/data.js
|
@ -2129,6 +2129,67 @@ module.exports = {
|
||||||
mention_everyone: false,
|
mention_everyone: false,
|
||||||
tts: false
|
tts: false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
forwarded_image: { type: 0,
|
||||||
|
content: "",
|
||||||
|
mentions: [],
|
||||||
|
mention_roles: [],
|
||||||
|
attachments: [],
|
||||||
|
embeds: [],
|
||||||
|
timestamp: "2024-10-16T22:25:01.973000+00:00",
|
||||||
|
edited_timestamp: null,
|
||||||
|
flags: 16384,
|
||||||
|
components: [],
|
||||||
|
id: "1296237495993892916",
|
||||||
|
channel_id: "112760669178241024",
|
||||||
|
author: {
|
||||||
|
id: "113340068197859328",
|
||||||
|
username: "kumaccino",
|
||||||
|
avatar: "a8829abe66866d7797b36f0bfac01086",
|
||||||
|
discriminator: "0",
|
||||||
|
public_flags: 128,
|
||||||
|
flags: 128,
|
||||||
|
banner: null,
|
||||||
|
accent_color: null,
|
||||||
|
global_name: "kumaccino",
|
||||||
|
avatar_decoration_data: null,
|
||||||
|
banner_color: null,
|
||||||
|
clan: null
|
||||||
|
},
|
||||||
|
pinned: false,
|
||||||
|
mention_everyone: false,
|
||||||
|
tts: false,
|
||||||
|
message_reference: {
|
||||||
|
type: 1,
|
||||||
|
channel_id: "1019762340922663022",
|
||||||
|
message_id: "1019779830469894234"
|
||||||
|
},
|
||||||
|
position: 0,
|
||||||
|
message_snapshots: [
|
||||||
|
{
|
||||||
|
message: {
|
||||||
|
type: 0,
|
||||||
|
content: "",
|
||||||
|
mentions: [],
|
||||||
|
mention_roles: [],
|
||||||
|
attachments: [
|
||||||
|
{
|
||||||
|
id: "1296237494987133070",
|
||||||
|
filename: "100km.gif",
|
||||||
|
size: 2965649,
|
||||||
|
url: "https://cdn.discordapp.com/attachments/112760669178241024/1296237494987133070/100km.gif?ex=67118ebd&is=67103d3d&hm=8ed76d424f92f11366989f2ebc713d4f8206706ef712571e934da45b59944f77&", proxy_url: "https://media.discordapp.net/attachments/112760669178241024/1296237494987133070/100km.gif?ex=67118ebd&is=67103d3d&hm=8ed76d424f92f11366989f2ebc713d4f8206706ef712571e934da45b59944f77&", width: 300,
|
||||||
|
height: 300,
|
||||||
|
content_type: "image/gif"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
embeds: [],
|
||||||
|
timestamp: "2022-09-15T01:20:58.177000+00:00",
|
||||||
|
edited_timestamp: null,
|
||||||
|
flags: 0,
|
||||||
|
components: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pk_message: {
|
pk_message: {
|
||||||
|
|
Loading…
Reference in a new issue