@@ -22,14 +22,18 @@ import {
2222 ActionException ,
2323 ActionExceptionKind ,
2424 ActionResult ,
25+ ClientCapabilitiesNegotiation ,
26+ ClientsInRoomMap ,
2527 Ok ,
28+ RoomCreator ,
2629 Task ,
2730 isError ,
2831} from "matrix-protection-suite" ;
2932import { Draupnir } from "../Draupnir" ;
3033import {
3134 ClientCapabilityFactory ,
3235 ClientForUserID ,
36+ joinedRoomsSafe ,
3337 RoomStateManagerFactory ,
3438} from "matrix-protection-suite-for-matrix-bot-sdk" ;
3539import {
@@ -43,9 +47,10 @@ import {
4347 StringRoomID ,
4448 MatrixRoomReference ,
4549 userLocalpart ,
46- isStringRoomID ,
50+ MatrixRoomID ,
4751} from "@the-draupnir-project/matrix-basic-types" ;
4852import { TopLevelStores } from "../backingstore/DraupnirStores" ;
53+ import { Result } from "@gnuxie/typescript-result" ;
4954
5055const log = new Logger ( "AppServiceDraupnirManager" ) ;
5156
@@ -66,6 +71,7 @@ export class AppServiceDraupnirManager {
6671 private readonly roomStateManagerFactory : RoomStateManagerFactory ,
6772 stores : TopLevelStores ,
6873 private readonly clientCapabilityFactory : ClientCapabilityFactory ,
74+ private readonly clientsInRoomMap : ClientsInRoomMap ,
6975 clientProvider : ClientForUserID ,
7076 private readonly instanceCountGauge : Gauge < "status" | "uuid" >
7177 ) {
@@ -102,6 +108,7 @@ export class AppServiceDraupnirManager {
102108 roomStateManagerFactory : RoomStateManagerFactory ,
103109 stores : TopLevelStores ,
104110 clientCapabilityFactory : ClientCapabilityFactory ,
111+ clientsInRoomMap : ClientsInRoomMap ,
105112 clientProvider : ClientForUserID ,
106113 instanceCountGauge : Gauge < "status" | "uuid" >
107114 ) : Promise < AppServiceDraupnirManager > {
@@ -113,6 +120,7 @@ export class AppServiceDraupnirManager {
113120 roomStateManagerFactory ,
114121 stores ,
115122 clientCapabilityFactory ,
123+ clientsInRoomMap ,
116124 clientProvider ,
117125 instanceCountGauge
118126 ) ;
@@ -202,26 +210,36 @@ export class AppServiceDraupnirManager {
202210 if ( provisionedMjolnirs . length === 0 ) {
203211 const mjolnirLocalPart = `draupnir_${ randomUUID ( ) } ` ;
204212 const mjIntent = await this . makeMatrixIntent ( mjolnirLocalPart ) ;
205-
206- const managementRoomID = await mjIntent . matrixClient . createRoom ( {
207- preset : "private_chat" ,
208- invite : [ requestingUserID ] ,
209- name : `${ requestingUserID } 's Draupnir` ,
210- power_level_content_override : {
211- users : {
212- [ requestingUserID ] : 100 ,
213- // Give the draupnir a higher PL so that can avoid issues with managing the management room.
214- [ await mjIntent . matrixClient . getUserId ( ) ] : 101 ,
215- } ,
216- } ,
217- } ) ;
218- if ( ! isStringRoomID ( managementRoomID ) ) {
219- throw new TypeError ( `${ managementRoomID } malformed managmentRoomID` ) ;
213+ const draupnirUserID = StringUserID ( mjIntent . userId ) ;
214+ // we need to make sure the client rooms are available for the capability factory
215+ const clientRooms = await this . clientsInRoomMap . makeClientRooms (
216+ draupnirUserID ,
217+ async ( ) => joinedRoomsSafe ( mjIntent . matrixClient )
218+ ) ;
219+ if ( isError ( clientRooms ) ) {
220+ return clientRooms . elaborate (
221+ "Unable to make client rooms for draupnir"
222+ ) ;
223+ }
224+ const clientPlatform = this . clientCapabilityFactory . makeClientPlatform (
225+ draupnirUserID ,
226+ mjIntent . matrixClient
227+ ) ;
228+ const managementRoom = await makeManagementRoom (
229+ clientPlatform . toRoomCreator ( ) ,
230+ clientPlatform . toClientCapabilitiesNegotiation ( ) ,
231+ requestingUserID ,
232+ draupnirUserID
233+ ) ;
234+ if ( isError ( managementRoom ) ) {
235+ return managementRoom . elaborate (
236+ "Failed to create management room for draupnir"
237+ ) ;
220238 }
221239 const draupnir = await this . makeInstance (
222240 mjolnirLocalPart ,
223241 requestingUserID ,
224- managementRoomID ,
242+ managementRoom . ok . toRoomIDOrAlias ( ) ,
225243 mjIntent . matrixClient
226244 ) ;
227245 if ( isError ( draupnir ) ) {
@@ -238,7 +256,7 @@ export class AppServiceDraupnirManager {
238256 const record = {
239257 local_part : mjolnirLocalPart ,
240258 owner : requestingUserID ,
241- management_room : managementRoomID ,
259+ management_room : managementRoom . ok . toRoomIDOrAlias ( ) ,
242260 } as MjolnirRecord ;
243261 await this . dataStore . store ( record ) ;
244262 return Ok ( record ) ;
@@ -424,3 +442,38 @@ async function createFirstList(
424442 policyRoom . ok
425443 ) ;
426444}
445+
446+ export async function makeManagementRoom (
447+ roomCreator : RoomCreator ,
448+ clientCapabilitiesNegotiation : ClientCapabilitiesNegotiation ,
449+ requestingUserID : StringUserID ,
450+ draupnirUserID : StringUserID
451+ ) : Promise < Result < MatrixRoomID > > {
452+ const capabilities =
453+ await clientCapabilitiesNegotiation . getClientCapabilities ( ) ;
454+ if ( isError ( capabilities ) ) {
455+ return capabilities . elaborate (
456+ "Failed to fetch room versions from client capabilities"
457+ ) ;
458+ }
459+ const isV12OrAboveDefault =
460+ capabilities . ok . capabilities [ "m.room_versions" ] . default >= "12" ;
461+ return await roomCreator . createRoom ( {
462+ preset : "private_chat" ,
463+ invite : [ requestingUserID ] ,
464+ name : `${ requestingUserID } 's Draupnir` ,
465+ power_level_content_override : isV12OrAboveDefault
466+ ? {
467+ users : {
468+ [ requestingUserID ] : 150 ,
469+ } ,
470+ }
471+ : {
472+ users : {
473+ [ requestingUserID ] : 100 ,
474+ // Give the draupnir a higher PL so that can avoid issues with managing the management room.
475+ [ draupnirUserID ] : 101 ,
476+ } ,
477+ } ,
478+ } ) ;
479+ }
0 commit comments