Make the link button do something
This commit is contained in:
		
							parent
							
								
									da5525a542
								
							
						
					
					
						commit
						c127923f4d
					
				
					 3 changed files with 70 additions and 5 deletions
				
			
		|  | @ -205,7 +205,7 @@ block body | |||
|               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 | ||||
|     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 | ||||
|         each channel in unlinkedChannels | ||||
|           input.s-btn--radio(type="radio" name="discord" id=channel.id value=channel.id) | ||||
|  | @ -220,7 +220,8 @@ block body | |||
|             +matrix(room, true) | ||||
|         else | ||||
|           .s-empty-state.p8 All Matrix rooms are linked. | ||||
|       input(type="hidden" name="guild_id" value=guild_id) | ||||
|       div | ||||
|         button.s-btn.s-btn__icon.s-btn__filled | ||||
|           != icons.Icons.IconLink | ||||
|           = ` Connect` | ||||
|         button.s-btn.s-btn__icon.s-btn__filled.htmx-indicator | ||||
|           != icons.Icons.IconMerge | ||||
|           = ` 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-discord") | ||||
| sync.require("./routes/invite") | ||||
| sync.require("./routes/guild-settings") | ||||
| sync.require("./routes/invite") | ||||
| sync.require("./routes/link") | ||||
| sync.require("./routes/oauth") | ||||
| sync.require("./routes/qr") | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue