@@ -7,7 +7,7 @@ import { isDeletedMessage, isMessageFromMatrixFederation, type IMessage, type IR
77import { Emitter } from '@rocket.chat/emitter' ;
88import { Router } from '@rocket.chat/http-router' ;
99import { Logger } from '@rocket.chat/logger' ;
10- import { MatrixBridgedUser , MatrixBridgedRoom , Users , Subscriptions , Messages } from '@rocket.chat/models' ;
10+ import { MatrixBridgedUser , MatrixBridgedRoom , Users , Subscriptions , Messages , Rooms } from '@rocket.chat/models' ;
1111import emojione from 'emojione' ;
1212
1313import { getWellKnownRoutes } from './api/.well-known/server' ;
@@ -380,4 +380,92 @@ export class FederationMatrix extends ServiceClass implements IFederationMatrixS
380380 throw error ;
381381 }
382382 }
383+
384+ async leaveRoom ( roomId : string , user : IUser ) : Promise < void > {
385+ try {
386+ const room = await Rooms . findOneById ( roomId ) ;
387+ if ( ! room ?. federated ) {
388+ this . logger . debug ( `Room ${ roomId } is not federated, skipping leave operation` ) ;
389+ return ;
390+ }
391+
392+ const matrixRoomId = await MatrixBridgedRoom . getExternalRoomId ( roomId ) ;
393+ if ( ! matrixRoomId ) {
394+ this . logger . warn ( `No Matrix room mapping found for federated room ${ roomId } , skipping leave` ) ;
395+ return ;
396+ }
397+
398+ const matrixDomain = await this . getMatrixDomain ( ) ;
399+ const matrixUserId = `@${ user . username } :${ matrixDomain } ` ;
400+ const existingMatrixUserId = await MatrixBridgedUser . getExternalUserIdByLocalUserId ( user . _id ) ;
401+
402+ if ( ! existingMatrixUserId ) {
403+ // User might not have been bridged yet if they never sent a message
404+ await MatrixBridgedUser . createOrUpdateByLocalId ( user . _id , matrixUserId , true , matrixDomain ) ;
405+ }
406+
407+ if ( ! this . homeserverServices ) {
408+ this . logger . warn ( 'Homeserver services not available, skipping room leave' ) ;
409+ return ;
410+ }
411+
412+ const actualMatrixUserId = existingMatrixUserId || matrixUserId ;
413+
414+ await this . homeserverServices . room . leaveRoom ( matrixRoomId , actualMatrixUserId ) ;
415+
416+ this . logger . info ( `User ${ user . username } left Matrix room ${ matrixRoomId } successfully` ) ;
417+ } catch ( error ) {
418+ this . logger . error ( 'Failed to leave room in Matrix:' , error ) ;
419+ throw error ;
420+ }
421+ }
422+
423+ async kickUser ( roomId : string , removedUser : IUser , userWhoRemoved : IUser ) : Promise < void > {
424+ try {
425+ const room = await Rooms . findOneById ( roomId ) ;
426+ if ( ! room ?. federated ) {
427+ this . logger . debug ( `Room ${ roomId } is not federated, skipping kick operation` ) ;
428+ return ;
429+ }
430+
431+ const matrixRoomId = await MatrixBridgedRoom . getExternalRoomId ( roomId ) ;
432+ if ( ! matrixRoomId ) {
433+ this . logger . warn ( `No Matrix room mapping found for federated room ${ roomId } , skipping kick` ) ;
434+ return ;
435+ }
436+
437+ const matrixDomain = await this . getMatrixDomain ( ) ;
438+
439+ const kickedMatrixUserId = `@${ removedUser . username } :${ matrixDomain } ` ;
440+ const existingKickedMatrixUserId = await MatrixBridgedUser . getExternalUserIdByLocalUserId ( removedUser . _id ) ;
441+ if ( ! existingKickedMatrixUserId ) {
442+ await MatrixBridgedUser . createOrUpdateByLocalId ( removedUser . _id , kickedMatrixUserId , true , matrixDomain ) ;
443+ }
444+ const actualKickedMatrixUserId = existingKickedMatrixUserId || kickedMatrixUserId ;
445+
446+ const senderMatrixUserId = `@${ userWhoRemoved . username } :${ matrixDomain } ` ;
447+ const existingSenderMatrixUserId = await MatrixBridgedUser . getExternalUserIdByLocalUserId ( userWhoRemoved . _id ) ;
448+ if ( ! existingSenderMatrixUserId ) {
449+ await MatrixBridgedUser . createOrUpdateByLocalId ( userWhoRemoved . _id , senderMatrixUserId , true , matrixDomain ) ;
450+ }
451+ const actualSenderMatrixUserId = existingSenderMatrixUserId || senderMatrixUserId ;
452+
453+ if ( ! this . homeserverServices ) {
454+ this . logger . warn ( 'Homeserver services not available, skipping user kick' ) ;
455+ return ;
456+ }
457+
458+ await this . homeserverServices . room . kickUser (
459+ matrixRoomId ,
460+ actualKickedMatrixUserId ,
461+ actualSenderMatrixUserId ,
462+ `Kicked by ${ userWhoRemoved . username } ` ,
463+ ) ;
464+
465+ this . logger . info ( `User ${ removedUser . username } was kicked from Matrix room ${ matrixRoomId } by ${ userWhoRemoved . username } ` ) ;
466+ } catch ( error ) {
467+ this . logger . error ( 'Failed to kick user from Matrix room:' , error ) ;
468+ throw error ;
469+ }
470+ }
383471}
0 commit comments