From 9c9dd97f3376505a221c8193e19291646e43af4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20H=C3=BCttemann?= Date: Thu, 14 Sep 2023 16:25:17 +0200 Subject: [PATCH] Remove excess members from rooms --- src/app.ts | 76 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/src/app.ts b/src/app.ts index dc50312..2155df2 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,18 +1,26 @@ import dotenv from 'dotenv' dotenv.config() +import { AxiosError } from 'axios' import lineByLine from 'n-readlines' import 'reflect-metadata' -import { handle as handleRoom } from './handlers/rooms' -import { handle as handleUser } from './handlers/users' -import { handle as handleMessage } from './handlers/messages' -import log from './helpers/logger' -import { initStorage } from './helpers/storage' -import { whoami } from './helpers/synapse' import { Entity, entities } from './Entities' -import { AxiosError } from 'axios' +import { handle as handleMessage } from './handlers/messages' +import { getFilteredMembers, handle as handleRoom } from './handlers/rooms' +import { handle as handleUser } from './handlers/users' +import log from './helpers/logger' +import { + getAllMappingsByType, + getMappingByMatrixId, + getMemberships, + initStorage, +} from './helpers/storage' +import { axios, formatUserSessionOptions, whoami } from './helpers/synapse' + +const applicationServiceToken = process.env.AS_TOKEN || '' log.info('rocketchat2matrix starts.') +// eslint-disable-next-line @typescript-eslint/no-unused-vars async function loadRcExport(entity: Entity) { const rl = new lineByLine(`./inputs/${entities[entity].filename}`) @@ -38,6 +46,57 @@ async function loadRcExport(entity: Entity) { } } +async function removeExcessRoomMembers() { + const roomMappings = await getAllMappingsByType( + entities[Entity.Rooms].mappingType + ) + if (!roomMappings) { + throw new Error(`No room mappings found`) + } + + roomMappings.forEach(async (roomMapping) => { + log.info( + `Checking memberships for room ${roomMapping.rcId} / ${roomMapping.matrixId}:` + ) + // get all memberships from db + const rcMemberIds = await getMemberships(roomMapping.rcId) + const memberMappings = await getFilteredMembers(rcMemberIds, '') + const memberNames: string[] = memberMappings.map( + (memberMapping) => memberMapping.matrixId || '' + ) + // get each mx rooms' mx users + const actualMembers: string[] = Object.keys( + ( + await axios.get( + `/_matrix/client/v3/rooms/${roomMapping.matrixId}/joined_members`, + formatUserSessionOptions(applicationServiceToken) + ) + ).data.joined + ) + + // do action for any user in mx, but not in rc + await Promise.all( + actualMembers.map(async (actualMember) => { + if (!memberNames.includes(actualMember)) { + log.warn( + `Member ${actualMember} should not be in room ${roomMapping.matrixId}, removing` + ) + const memberMapping = await getMappingByMatrixId(actualMember) + if (!memberMapping || !memberMapping.accessToken) { + throw new Error(`Could not find access token for member ${actualMember}, this is a bug`) + } + + await axios.post( + `/_matrix/client/v3/rooms/${roomMapping.matrixId}/leave`, + {}, + formatUserSessionOptions(memberMapping.accessToken) + ) + } + }) + ) + }) +} + async function main() { try { await whoami() @@ -48,6 +107,9 @@ async function main() { await loadRcExport(Entity.Rooms) log.info('Parsing messages') await loadRcExport(Entity.Messages) + log.info('Checking room memberships') + await removeExcessRoomMembers() + log.info('Done.') } catch (error) { if (error instanceof AxiosError) {