4 process.env.DISABLE_API_LISTEN = '1';
6 const path = require('path');
7 const fs = require('fs');
8 const yargs = require('yargs');
9 const LineByLineReader = require('line-by-line');
10 const shutdown = require('shutdown');
11 const persistence = require('gitter-web-persistence');
12 const troupeService = require('gitter-web-rooms/lib/troupe-service');
14 const installBridge = require('gitter-web-matrix-bridge');
15 const matrixBridge = require('gitter-web-matrix-bridge/lib/matrix-bridge');
16 const MatrixUtils = require('gitter-web-matrix-bridge/lib/matrix-utils');
18 const matrixUtils = new MatrixUtils(matrixBridge);
21 .option('room-store-file', {
23 description: 'path to the room store file (room-store.db)',
31 description: 'Delay(in milliseconds) between rooms to update to not overwhelm the homeserver'
34 description: 'Dry-run. Do not execute, just print',
39 .alias('help', 'h').argv;
41 async function migrateRoom(roomEntry) {
42 console.log('Migrating roomEntry', roomEntry);
45 const matrixRoomId = roomEntry.matrix_id;
46 const gitterRoomUri = roomEntry.remote_id;
48 const gitterRoom = await troupeService.findByUri(gitterRoomUri);
50 const bridgeIntent = matrixBridge.getIntent();
51 await bridgeIntent.join(matrixRoomId, ['matrix.org']);
53 const existingPortalBridgeEntry = await persistence.MatrixBridgedRoom.findOne({
54 troupeId: gitterRoom.id
57 if (existingPortalBridgeEntry) {
59 `Found portal room that already exists as well ${existingPortalBridgeEntry.matrixRoomId}`
61 const matrixContent = {
62 body: `This room is being migrated, you can use [\`/join ${matrixRoomId} matrix.org\`](https://matrix.to/#/${matrixRoomId}?via=matrix.org) to get to the new room`,
63 formatted_body: `This room is being migrated, you can use <a href="https://matrix.to/#/${matrixRoomId}?via=matrix.org"><code>/join ${matrixRoomId} matrix.org</code></a> to get to the new room`,
64 format: 'org.matrix.custom.html',
67 const intent = matrixBridge.getIntent();
68 await intent.sendMessage(existingPortalBridgeEntry.matrixRoomId, matrixContent);
71 await persistence.MatrixBridgedRoom.update(
72 { troupeId: gitterRoom.id },
80 await matrixUtils.ensureRoomAliasesForGitterRoom(matrixRoomId, gitterRoom);
84 const FAILED_LOG_PATH = path.resolve('/tmp/failed-migrated-plumbed-matrix-rooms.db');
86 async function processLine(line) {
87 const roomEntry = JSON.parse(line);
89 console.log('Processing roomEntry', roomEntry);
91 if (!roomEntry.matrix_id || !roomEntry.remote_id) {
94 // We're only looking for plumbed rooms
95 if (roomEntry && roomEntry.data && roomEntry.data.portal) {
100 await migrateRoom(roomEntry);
102 console.error('Error migrating room', err, err.stack);
103 fs.appendFileSync(FAILED_LOG_PATH, JSON.stringify(roomEntry) + '\n');
106 // Put a delay between each time we process a room
107 // to avoid overwhelming and hitting the rate-limits on the Matrix homeserver
108 if (opts.delay > 0) {
109 await new Promise(resolve => {
110 setTimeout(resolve, opts.delay);
115 async function run() {
117 fs.writeFileSync(FAILED_LOG_PATH, '');
119 console.log('Failed to create the log file for failed rooms');
124 console.log('Setting up Matrix bridge');
125 await installBridge();
127 const lr = new LineByLineReader(opts.roomStoreFile);
129 lr.on('error', err => {
130 console.error('Error while reading lines', err);
131 shutdown.shutdownGracefully(1);
134 lr.on('line', async line => {
138 await processLine(line);
140 console.error(err, err.stack);
147 console.log('All lines processed');
149 shutdown.shutdownGracefully();
152 console.error(err, err.stack);
153 shutdown.shutdownGracefully(1);