From a7ff3a13cd07e6a9393752a0a4b81962518775e5 Mon Sep 17 00:00:00 2001
From: Will Hunt <will@half-shot.uk>
Date: Sun, 27 Jan 2019 17:25:11 +0000
Subject: [PATCH] Migrate rooms in the schema

---
 src/db/schema/dbschema.ts  |   1 +
 src/db/schema/v8.ts        |  29 +++++++++-
 src/discordas.ts           |   2 +-
 src/store.ts               |  14 ++++-
 tools/moveRoomStoreToDb.ts | 106 -------------------------------------
 5 files changed, 42 insertions(+), 110 deletions(-)
 delete mode 100644 tools/moveRoomStoreToDb.ts

diff --git a/src/db/schema/dbschema.ts b/src/db/schema/dbschema.ts
index 9f215f1..132e7c0 100644
--- a/src/db/schema/dbschema.ts
+++ b/src/db/schema/dbschema.ts
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import { DiscordStore } from "../../store";
+import { DiscordBridgeConfigDatabase } from "../../config";
 export interface IDbSchema {
     description: string;
     run(store: DiscordStore): Promise<null|void|Error|Error[]>;
diff --git a/src/db/schema/v8.ts b/src/db/schema/v8.ts
index 4e68102..b41650e 100644
--- a/src/db/schema/v8.ts
+++ b/src/db/schema/v8.ts
@@ -17,11 +17,19 @@ limitations under the License.
 import {IDbSchema} from "./dbschema";
 import {DiscordStore} from "../../store";
 import { Log } from "../../log";
-
+import {
+    RoomStore,
+} from "matrix-appservice-bridge";
+import { RemoteStoreRoom, MatrixStoreRoom } from "../roomstore";
 const log = new Log("SchemaV8");
 
 export class Schema implements IDbSchema {
     public description = "create room store tables";
+
+    constructor(private roomStore: RoomStore|null) {
+
+    }
+
     public async run(store: DiscordStore): Promise<void> {
         await store.create_table(`
             CREATE TABLE remote_room_data (
@@ -47,6 +55,25 @@ export class Schema implements IDbSchema {
                 remote_id TEXT,
                 PRIMARY KEY(id)
         );`, "room_entries");
+
+        if (this.roomStore === null) {
+            log.warn("Not migrating rooms from room store, room store is null");
+            return;
+        }
+        log.warn("Migrating rooms from roomstore, this may take a while...");
+        const rooms = await this.roomStore.select({});
+        // Matrix room only entrys are useless.
+        const entrys = rooms.filter((r) => r.remote);
+        for (const e of entrys) {
+            const matrix = new MatrixStoreRoom(e.matrix_id);
+            try {
+                const remote = new RemoteStoreRoom(e.remote_id, e.remote);
+                await store.roomStore.linkRooms(matrix, remote);
+                log.info(`Migrated ${matrix.roomId}`);
+            } catch (ex) {
+                log.error(`Failed to link ${matrix.roomId}: `, ex);
+            }
+        }
     }
 
     public async rollBack(store: DiscordStore): Promise<void> {
diff --git a/src/discordas.ts b/src/discordas.ts
index 5e66cb7..841747a 100644
--- a/src/discordas.ts
+++ b/src/discordas.ts
@@ -136,7 +136,7 @@ async function run(port: number, fileConfig: DiscordBridgeConfig) {
     try {
         await bridge.run(port, config);
         log.info("Initing store.");
-        await discordstore.init();
+        await discordstore.init(0, bridge.getRoomStore());
         log.info("Initing bot.");
         provisioner.setStore(discordstore.roomStore);
         roomhandler.setBridge(bridge, discordstore.roomStore);
diff --git a/src/store.ts b/src/store.ts
index c18ef89..0a506a4 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -25,6 +25,9 @@ import { DiscordBridgeConfigDatabase } from "./config";
 import { Postgres } from "./db/postgres";
 import { IDatabaseConnector } from "./db/connector";
 import { DbRoomStore } from "./db/roomstore";
+import {
+    RoomStore,
+} from "matrix-appservice-bridge";
 const log = new Log("DiscordStore");
 /**
  * Stores data for specific users and data not specific to rooms.
@@ -83,7 +86,8 @@ export class DiscordStore {
     /**
      * Checks the database has all the tables needed.
      */
-    public async init(overrideSchema: number = 0): Promise<void> {
+    public async init(overrideSchema: number = 0, roomStore: RoomStore = null): Promise<void> {
+        const SCHEMA_ROOM_STORE_REQUIRED = 8;
         log.info("Starting DB Init");
         await this.open_database();
         let version = await this.getSchemaVersion();
@@ -91,7 +95,13 @@ export class DiscordStore {
         while (version < targetSchema) {
             version++;
             const schemaClass = require(`./db/schema/v${version}.js`).Schema;
-            const schema = (new schemaClass() as IDbSchema);
+            let schema: IDbSchema;
+            if (version === SCHEMA_ROOM_STORE_REQUIRED) { // 8 requires access to the roomstore.
+                console.log(roomStore);
+                schema = (new schemaClass(roomStore) as IDbSchema);
+            } else {
+                schema = (new schemaClass() as IDbSchema);
+            }
             log.info(`Updating database to v${version}, "${schema.description}"`);
             try {
                 await schema.run(this);
diff --git a/tools/moveRoomStoreToDb.ts b/tools/moveRoomStoreToDb.ts
deleted file mode 100644
index 80edb1b..0000000
--- a/tools/moveRoomStoreToDb.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-Copyright 2018 matrix-appservice-discord
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-/* tslint:disable:no-console */
-/**
- * Allows you to become an admin for a room the bot is in control of.
- */
-
-import { ClientFactory, Bridge } from "matrix-appservice-bridge";
-import * as yaml from "js-yaml";
-import * as fs from "fs";
-import * as args from "command-line-args";
-import * as usage from "command-line-usage";
-import { DiscordBridgeConfig } from "../src/config";
-import { Log } from "../src/log";
-import { Util } from "../src/util";
-import { RemoteStoreRoom, MatrixStoreRoom } from "../src/db/roomstore";
-import { DiscordStore } from "../src/store";
-const log = new Log("MoveRoomStoreToDb");
-
-const optionDefinitions = [
-    {
-        alias: "h",
-        description: "Display this usage guide.",
-        name: "help",
-        type: Boolean,
-    },
-    {
-        alias: "c",
-        defaultValue: "config.yaml",
-        description: "The AS config file.",
-        name: "config",
-        type: String,
-        typeLabel: "<config.yaml>",
-    },
-    {
-        alias: "s",
-        defaultValue: "room-store.db",
-        description: "The location of the room store.",
-        name: "store",
-        type: String,
-    },
-];
-
-const options = args(optionDefinitions);
-
-if (options.help) {
-    /* tslint:disable:no-console */
-    console.log(usage([
-    {
-        content: "A tool to move all room store entries to the database.",
-        header: "Add rooms to directory",
-    },
-    {
-        header: "Options",
-        optionList: optionDefinitions,
-    },
-    ]));
-    process.exit(0);
-}
-const config: DiscordBridgeConfig = yaml.safeLoad(fs.readFileSync(options.config, "utf8")) as DiscordBridgeConfig;
-
-const bridge = new Bridge({
-    controller: {
-        onEvent: () => { },
-    },
-    domain: "rubbish",
-    homeserverUrl: true,
-    registration: true,
-    roomStore: options.store,
-});
-
-async function run() {
-    await bridge.loadDatabases();
-    const store = new DiscordStore(config.database);
-    await store.init();
-    const rooms = await bridge.getRoomStore().select({});
-    // Matrix room only entrys are useless.
-    const entrys = rooms.filter((r) => r.remote);
-    entrys.forEach((e) => {
-        const remote = new RemoteStoreRoom(e.remote_id, e.remote);
-        const matrix = new MatrixStoreRoom(e.matrix_id);
-        store.roomStore.linkRooms(matrix, remote).then(() => {
-            log.info(`Migrated ${matrix.roomId}`);
-        }).catch((err) => {
-            log.error(`Failed to link ${matrix.roomId}: `, err);
-        });
-    });
-}
-
-run().catch((e) => {
-    log.error(`Failed to run script`, e);
-});
-- 
GitLab