diff --git a/provisioner-rules.yaml b/provisioner-rules.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c1fdb6eba67b8282617241e6667bb2d3262c65fa --- /dev/null +++ b/provisioner-rules.yaml @@ -0,0 +1,15 @@ +# This rule checks the memberlist of a room to determine if it will let +# the bridge create a link to the room. This is useful for avoiding conflicts +# with other bridges. +userIds: + # Anyone in this set will be ALWAYS exempt from the conflicts rule. + # Here anyone who's localpart starts with nice is exempt. + exempt: + - "@nice+.:example.com" + - "@mr.e:localhost" + # This is a regex that will exclude anyone who has "guy" at the end of their localpart. + # evilbloke is also exempt. + conflict: + - "@+.guy:example.com" + - "@evilbloke:example.com" + - "@mr.*:localhost" diff --git a/src/bot.ts b/src/bot.ts index 47fddc3b9e3ce2ecf0143bbe20c3740471363307..eee7eb5424b3a83060dfa8979b4a7eb08de4d4de 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -63,11 +63,8 @@ interface IThirdPartyLookup { } export class DiscordBot { - private config: DiscordBridgeConfig; private clientFactory: DiscordClientFactory; - private store: DiscordStore; private bot: Discord.Client; - private bridge: Bridge; private presenceInterval: number; private sentMessages: string[]; private lastEventIds: { [channelId: string]: string }; @@ -77,35 +74,38 @@ export class DiscordBot { private userSync: UserSyncroniser; private channelSync: ChannelSyncroniser; private roomHandler: MatrixRoomHandler; + private provisioner: Provisioner; /* Caches */ private roomIdsForGuildCache: Map<string, {roomIds: string[], ts: number}>; /* Handles messages queued up to be sent to discord. */ private discordMessageQueue: { [channelId: string]: Promise<void> }; - constructor(config: DiscordBridgeConfig, store: DiscordStore, private provisioner: Provisioner) { - this.config = config; - this.store = store; - this.sentMessages = []; + constructor( + private botUserId: string, + private config: DiscordBridgeConfig, + private bridge: Bridge, + private store: DiscordStore, + ) { + + // create handlers + this.provisioner = new Provisioner(store.roomStore); this.clientFactory = new DiscordClientFactory(store, config.auth); this.discordMsgProcessor = new DiscordMessageProcessor( - new DiscordMessageProcessorOpts(this.config.bridge.domain, this), + new DiscordMessageProcessorOpts(config.bridge.domain, this), ); this.presenceHandler = new PresenceHandler(this); - this.discordMessageQueue = {}; - this.lastEventIds = {}; - } - - public setBridge(bridge: Bridge) { - this.bridge = bridge; + this.roomHandler = new MatrixRoomHandler(this, config, this.provisioner, bridge, store.roomStore); this.mxEventProcessor = new MatrixEventProcessor( - new MatrixEventProcessorOpts(this.config, bridge, this), + new MatrixEventProcessorOpts(config, bridge, this), ); - this.channelSync = new ChannelSyncroniser(this.bridge, this.config, this, this.store.roomStore); - } + this.channelSync = new ChannelSyncroniser(bridge, config, this, store.roomStore); + this.userSync = new UserSyncroniser(bridge, config, this); - public setRoomHandler(roomHandler: MatrixRoomHandler) { - this.roomHandler = roomHandler; + // init vars + this.sentMessages = []; + this.discordMessageQueue = {}; + this.lastEventIds = {}; } get ClientFactory(): DiscordClientFactory { @@ -120,6 +120,14 @@ export class DiscordBot { return this.channelSync; } + get BotUserId(): string { + return this.botUserId; + } + + get RoomHandler(): MatrixRoomHandler { + return this.roomHandler; + } + public GetIntentFromDiscordMember(member: Discord.GuildMember | Discord.User, webhookID?: string): Intent { if (webhookID) { // webhookID and user IDs are the same, they are unique, so no need to prefix _webhook_ @@ -130,8 +138,11 @@ export class DiscordBot { return this.bridge.getIntentFromLocalpart(`_discord_${member.id}`); } - public async run(): Promise<void> { + public async init(): Promise<void> { await this.clientFactory.init(); + } + + public async run(): Promise<void> { const client = await this.clientFactory.getClient(); if (!this.config.bridge.disableTypingNotifications) { @@ -224,7 +235,6 @@ export class DiscordBot { }); const jsLog = new Log("discord.js"); - this.userSync = new UserSyncroniser(this.bridge, this.config, this); client.on("userUpdate", async (_, user) => { try { await this.userSync.OnUpdateUser(user); @@ -831,7 +841,7 @@ export class DiscordBot { await afterSend(res); } catch (e) { if (e.errcode !== "M_FORBIDDEN" && e.errcode !== "M_GUEST_ACCESS_FORBIDDEN") { - log.error("DiscordBot", "Failed to send message into room.", e); + log.error("Failed to send message into room.", e); return; } if (msg.member) { diff --git a/src/clientfactory.ts b/src/clientfactory.ts index 0d584c2f8080b4c2b4f58abb8b02848cae10b2b5..72a5b57006a512f2051c3a43f34fd48887ba3124 100644 --- a/src/clientfactory.ts +++ b/src/clientfactory.ts @@ -22,7 +22,7 @@ import { Log } from "./log"; const log = new Log("ClientFactory"); -const READY_TIMEOUT = 5000; +const READY_TIMEOUT = 30000; export class DiscordClientFactory { private config: DiscordBridgeConfigAuth; diff --git a/src/discordas.ts b/src/discordas.ts index c445547842dd95daf5bc7abe500cb93bfdf0ea41..9115b3d6a5a5b11aa8958f5add2d4a6939372ca5 100644 --- a/src/discordas.ts +++ b/src/discordas.ts @@ -20,9 +20,7 @@ import * as yaml from "js-yaml"; import * as fs from "fs"; import { DiscordBridgeConfig } from "./config"; import { DiscordBot } from "./bot"; -import { MatrixRoomHandler } from "./matrixroomhandler"; import { DiscordStore } from "./store"; -import { Provisioner } from "./provisioner"; import { Log } from "./log"; import "source-map-support/register"; @@ -57,6 +55,9 @@ function generateRegistration(reg, callback) { callback(reg); } +// tslint:disable-next-line no-any +type callbackFn = (...args: any[]) => Promise<any>; + async function run(port: number, fileConfig: DiscordBridgeConfig) { const config = new DiscordBridgeConfig(); config.ApplyConfig(fileConfig); @@ -74,10 +75,9 @@ async function run(port: number, fileConfig: DiscordBridgeConfig) { token: registration.as_token, url: config.bridge.homeserverUrl, }); - const provisioner = new Provisioner(); - const discordstore = new DiscordStore(config.database); - const discordbot = new DiscordBot(config, discordstore, provisioner); - const roomhandler = new MatrixRoomHandler(discordbot, config, botUserId, provisioner); + const store = new DiscordStore(config.database); + + const callbacks: { [id: string]: callbackFn; } = {}; const bridge = new Bridge({ clientFactory, @@ -85,26 +85,30 @@ async function run(port: number, fileConfig: DiscordBridgeConfig) { // onUserQuery: userQuery, onAliasQueried: async (alias: string, roomId: string) => { try { - return await roomhandler.OnAliasQueried.bind(roomhandler)(alias, roomId); + return await callbacks.onAliasQueried(alias, roomId); } catch (err) { log.error("Exception thrown while handling \"onAliasQueried\" event", err); } }, onAliasQuery: async (alias: string, aliasLocalpart: string) => { try { - return await roomhandler.OnAliasQuery.bind(roomhandler)(alias, aliasLocalpart); + return await callbacks.onAliasQuery(alias, aliasLocalpart); } catch (err) { log.error("Exception thrown while handling \"onAliasQuery\" event", err); } }, onEvent: async (request) => { try { // Build our own context. + if (!store.roomStore) { + log.warn("Discord store not ready yet, dropping message"); + return; + } const roomId = request.getData().room_id; let context = {}; if (roomId) { - const entries = await discordstore.roomStore.getEntriesByMatrixId(request.getData().room_id); + const entries = await store.roomStore.getEntriesByMatrixId(request.getData().room_id); context = { rooms: entries[0], }; } - await request.outcomeFrom(Bluebird.resolve(roomhandler.OnEvent(request, context))); + await request.outcomeFrom(Bluebird.resolve(callbacks.OnEvent(request, context))); } catch (err) { log.error("Exception thrown while handling \"onEvent\" event", err); await request.outcomeFrom(Bluebird.reject("Failed to handle")); @@ -113,7 +117,13 @@ async function run(port: number, fileConfig: DiscordBridgeConfig) { onLog: (line, isError) => { log.verbose("matrix-appservice-bridge", line); }, - thirdPartyLookup: roomhandler.ThirdPartyLookup, + thirdPartyLookup: async () => { + try { + return await callbacks.thirdPartyLookup(); + } catch (err) { + log.error("Exception thrown while handling \"thirdPartyLookup\" event", err); + } + }, }, disableContext: true, domain: config.bridge.domain, @@ -131,23 +141,35 @@ async function run(port: number, fileConfig: DiscordBridgeConfig) { registration, userStore: config.database.userStorePath, }); - log.info("Initing bridge."); - log.info(`Started listening on port ${port}.`); + // Warn and deprecate old config options. + const discordbot = new DiscordBot(botUserId, config, bridge, store); + const roomhandler = discordbot.RoomHandler; + + try { + callbacks.onAliasQueried = roomhandler.OnAliasQueried.bind(roomhandler); + callbacks.onAliasQuery = roomhandler.OnAliasQuery.bind(roomhandler); + callbacks.onEvent = roomhandler.OnEvent.bind(roomhandler); + callbacks.thirdPartyLookup = async () => { + return roomhandler.ThirdPartyLookup; + }; + } catch (err) { + log.error("Failed to register callbacks. Exiting.", err); + process.exit(1); + } + + log.info("Initing bridge"); try { await bridge.run(port, config); - log.info("Initing store."); - await discordstore.init(0, bridge.getRoomStore()); - log.info("Initing bot."); - provisioner.setStore(discordstore.roomStore); - roomhandler.setBridge(bridge, discordstore.roomStore); - discordbot.setBridge(bridge); - discordbot.setRoomHandler(roomhandler); + log.info(`Started listening on port ${port}`); + await store.init(undefined, bridge.getRoomStore()); + log.info("Initing bot"); + await discordbot.init(); await discordbot.run(); - log.info("Discordbot started successfully."); + log.info("Discordbot started successfully"); } catch (err) { log.error(err); - log.error("Failure during startup. Exiting."); + log.error("Failure during startup. Exiting"); process.exit(1); } } diff --git a/src/matrixmessageprocessor.ts b/src/matrixmessageprocessor.ts index 562d20a30729cb5281bce536d4d87d4eca1ff434..e47f3efccf226cd8a6412ff1f903aa5af8587477 100644 --- a/src/matrixmessageprocessor.ts +++ b/src/matrixmessageprocessor.ts @@ -94,7 +94,7 @@ export class MatrixMessageProcessor { msg = msg.replace(/@room/g, "@here"); } } - const escapeChars = ["\\", "*", "_", "~", "`"]; + const escapeChars = ["\\", "*", "_", "~", "`", "|"]; msg = msg.split(" ").map((s) => { if (s.match(/^https?:\/\//)) { return s; diff --git a/src/matrixroomhandler.ts b/src/matrixroomhandler.ts index 75a9e1bb95111ae39c4094bbd7a4a6e14f0bab0f..032a77fb8ee1b556b363953ad15dc6aaf5e299ce 100644 --- a/src/matrixroomhandler.ts +++ b/src/matrixroomhandler.ts @@ -59,19 +59,16 @@ const JOIN_ROOM_SCHEDULE = [ /* tslint:enable:no-magic-numbers */ export class MatrixRoomHandler { - private bridge: Bridge; - private roomStore: DbRoomStore; + private botUserId: string; private botJoinedRooms: Set<string>; // roomids private botJoinedRoomsCacheUpdatedAt = 0; constructor( private discord: DiscordBot, private config: DiscordBridgeConfig, - private botUserId: string, private provisioner: Provisioner, - ) { - this.discord = discord; - this.config = config; - this.botUserId = botUserId; + private bridge: Bridge, + private roomStore: DbRoomStore) { + this.botUserId = this.discord.BotUserId; this.botJoinedRooms = new Set(); } @@ -86,11 +83,6 @@ export class MatrixRoomHandler { }; } - public setBridge(bridge: Bridge, roomStore: DbRoomStore) { - this.bridge = bridge; - this.roomStore = roomStore; - } - public async OnAliasQueried(alias: string, roomId: string) { log.verbose(`Got OnAliasQueried for ${alias} ${roomId}`); let channel: Discord.GuildChannel; diff --git a/src/presencehandler.ts b/src/presencehandler.ts index 9f1c1e2195891844ff469a8234d4bec7b381a667..24e6e7f7bf293a61e689c7fcb38d5fdc4ba412f6 100644 --- a/src/presencehandler.ts +++ b/src/presencehandler.ts @@ -32,11 +32,9 @@ interface IMatrixPresence { } export class PresenceHandler { - private readonly bot: DiscordBot; private presenceQueue: User[]; private interval: NodeJS.Timeout | null; - constructor(bot: DiscordBot) { - this.bot = bot; + constructor(private bot: DiscordBot) { this.presenceQueue = []; } diff --git a/src/provisioner.ts b/src/provisioner.ts index 4f11e990752448678c6679f63183e0410d7e40bc..9a871a1750fae09eb2f3592b24d1ba1488ccc55d 100644 --- a/src/provisioner.ts +++ b/src/provisioner.ts @@ -27,11 +27,8 @@ const PERMISSION_REQUEST_TIMEOUT = 300000; // 5 minutes export class Provisioner { private pendingRequests: Map<string, (approved: boolean) => void> = new Map(); // [channelId]: resolver fn - private roomStore: DbRoomStore; - constructor(roomStore: DbRoomStore) { - this.roomStore = roomStore; - } + constructor(private roomStore: DbRoomStore) { } public async BridgeMatrixRoom(channel: Discord.TextChannel, roomId: string) { const remote = new RemoteRoom(`discord_${channel.guild.id}_${channel.id}_bridged`); diff --git a/src/store.ts b/src/store.ts index 4e5dd9d0ec96c19faf8e440005550c838048c196..f17bf143a6c454755d93d389545d97afacaba0df 100644 --- a/src/store.ts +++ b/src/store.ts @@ -37,7 +37,7 @@ export class DiscordStore { private version: number; private config: DiscordBridgeConfigDatabase; private pRoomStore: DbRoomStore; - constructor(private configOrFile: DiscordBridgeConfigDatabase|string) { + constructor(configOrFile: DiscordBridgeConfigDatabase|string) { if (typeof(configOrFile) === "string") { this.config = new DiscordBridgeConfigDatabase(); this.config.filename = configOrFile; diff --git a/test/db/test_roomstore.ts b/test/db/test_roomstore.ts index 443794572e066ffb7e4a5cfc9866f701710c89ac..c94a796aba105b1f5bc7bb361f84cc139e559461 100644 --- a/test/db/test_roomstore.ts +++ b/test/db/test_roomstore.ts @@ -123,20 +123,20 @@ describe("RoomStore", () => { const EXPECTED_ROOMS = 2; await store.roomStore.upsertEntry({ id: "test4_1", - matrix: new MatrixStoreRoom("test4_m1"), + matrix: new MatrixStoreRoom("!test_mOne:eggs.com"), remote: new RemoteStoreRoom("test4_r", {discord_guild: "five", discord_channel: "five"}), }); await store.roomStore.upsertEntry({ id: "test4_2", - matrix: new MatrixStoreRoom("test4_m2"), + matrix: new MatrixStoreRoom("!test_mTwo:eggs.com"), remote: new RemoteStoreRoom("test4_r", {discord_guild: "nine", discord_channel: "nine"}), }); - const entries = await store.roomStore.getEntriesByMatrixIds(["test4_m1", "test4_m2"]); + const entries = await store.roomStore.getEntriesByMatrixIds(["!test_mOne:eggs.com", "!test_mTwo:eggs.com"]); expect(entries).to.have.lengthOf(EXPECTED_ROOMS); expect(entries[0].id).to.equal("test4_1"); - expect(entries[0].matrix!.roomId).to.equal("test4_m1"); + expect(entries[0].matrix!.roomId).to.equal("!test_mOne:eggs.com"); expect(entries[1].id).to.equal("test4_2"); - expect(entries[1].matrix!.roomId).to.equal("test4_m2"); + expect(entries[1].matrix!.roomId).to.equal("!test_mTwo:eggs.com"); }); }); describe("linkRooms", () => { diff --git a/test/test_discordbot.ts b/test/test_discordbot.ts index d757a73a1545092c04e881f5d9d347a1c9ca8877..d6dcd1b3a2c1d9484bf60e5daced3b600cf04e14 100644 --- a/test/test_discordbot.ts +++ b/test/test_discordbot.ts @@ -89,10 +89,11 @@ describe("DiscordBot", () => { describe("run()", () => { it("should resolve when ready.", async () => { discordBot = new modDiscordBot.DiscordBot( + "", config, - { }, + mockBridge, + {}, ); - discordBot.setBridge(mockBridge); await discordBot.run(); }); }); @@ -100,10 +101,11 @@ describe("DiscordBot", () => { describe("LookupRoom()", () => { beforeEach( async () => { discordBot = new modDiscordBot.DiscordBot( + "", config, - { }, + mockBridge, + {}, ); - discordBot.setBridge(mockBridge); await discordBot.run(); }); it("should reject a missing guild.", async () => { @@ -141,8 +143,10 @@ describe("DiscordBot", () => { ATTACHMENT = {}; MSGTYPE = ""; const discord = new modDiscordBot.DiscordBot( + "", config, mockBridge, + {}, ); discord.bot = { user: { id: "654" } }; discord.provisioner = { @@ -294,8 +298,10 @@ describe("DiscordBot", () => { describe("OnMessageUpdate()", () => { it("should return on an unchanged message", async () => { discordBot = new modDiscordBot.DiscordBot( + "", config, mockBridge, + {}, ); const guild: any = new MockGuild("123", []); @@ -319,8 +325,10 @@ describe("DiscordBot", () => { }); it("should send a matrix message on an edited discord message", async () => { discordBot = new modDiscordBot.DiscordBot( + "", config, mockBridge, + {}, ); discordBot.store.Get = (a, b) => null; @@ -345,8 +353,10 @@ describe("DiscordBot", () => { }); it("should delete and re-send if it is the newest message", async () => { discordBot = new modDiscordBot.DiscordBot( + "", config, mockBridge, + {}, ); discordBot.store.Get = (a, b) => { return { MatrixId: "$event:localhost;!room:localhost", @@ -380,8 +390,10 @@ describe("DiscordBot", () => { describe("event:message", () => { it("should delay messages so they arrive in order", async () => { discordBot = new modDiscordBot.DiscordBot( + "", config, mockBridge, + {}, ); let expected = 0; discordBot.OnMessage = async (msg: any) => { @@ -389,7 +401,6 @@ describe("DiscordBot", () => { expected++; }; const client: MockDiscordClient = (await discordBot.ClientFactory.getClient()) as MockDiscordClient; - discordBot.setBridge(mockBridge); await discordBot.run(); const ITERATIONS = 25; const CHANID = 123; @@ -401,8 +412,10 @@ describe("DiscordBot", () => { }); it("should handle messages that reject in the queue", async () => { discordBot = new modDiscordBot.DiscordBot( + "", config, mockBridge, + {}, ); let expected = 0; const THROW_EVERY = 5; @@ -415,7 +428,6 @@ describe("DiscordBot", () => { return Promise.resolve(); }; const client: MockDiscordClient = (await discordBot.ClientFactory.getClient()) as MockDiscordClient; - discordBot.setBridge(mockBridge); await discordBot.run(); const ITERATIONS = 25; const CHANID = 123; @@ -444,7 +456,6 @@ describe("DiscordBot", () => { // const discordBot = new modDiscordBot.DiscordBot( // config, // ); - // discordBot.setBridge(mockBridge); // discordBot.run(); // it("should reject an unknown room.", () => { // return assert.isRejected(discordBot.OnTyping( {id: "512"}, {id: "12345"}, true)); diff --git a/test/test_matrixmessageprocessor.ts b/test/test_matrixmessageprocessor.ts index a823c651c285be8f3407472d442a31fa29be22ca..66fced8ee3fe2e238c8ea451dd0aa92924981316 100644 --- a/test/test_matrixmessageprocessor.ts +++ b/test/test_matrixmessageprocessor.ts @@ -98,6 +98,13 @@ describe("MatrixMessageProcessor", () => { const result = await mp.FormatMessage(msg, guild as any); expect(result).is.equal("wow \\\\\\*this\\\\\\* is cool"); }); + it("escapes ALL the stuff", async () => { + const mp = new MatrixMessageProcessor(bot); + const guild = new MockGuild("1234"); + const msg = getPlainMessage("\\ * _ ~ ` |"); + const result = await mp.FormatMessage(msg, guild as any); + expect(result).is.equal("\\\\ \\* \\_ \\~ \\` \\|"); + }); }); describe("FormatMessage / formatted_body / simple", () => { it("leaves blank stuff untouched", async () => { diff --git a/test/test_matrixroomhandler.ts b/test/test_matrixroomhandler.ts index 39ce63e026229866d34ec1a05ceaf1aa41c1776b..1aa82ad4d68709af01549310db8aad1134f91c6f 100644 --- a/test/test_matrixroomhandler.ts +++ b/test/test_matrixroomhandler.ts @@ -17,15 +17,9 @@ limitations under the License. import * as Chai from "chai"; import * as Proxyquire from "proxyquire"; import {DiscordBridgeConfig} from "../src/config"; -import {MockDiscordClient} from "./mocks/discordclient"; -import {PresenceHandler} from "../src/presencehandler"; -import {DiscordBot} from "../src/bot"; -import {MatrixRoomHandler} from "../src/matrixroomhandler"; import {MockChannel} from "./mocks/channel"; import {MockMember} from "./mocks/member"; -import * as Bluebird from "bluebird"; import {MockGuild} from "./mocks/guild"; -import {Guild} from "discord.js"; import { Util } from "../src/util"; // we are a test file and thus need those @@ -33,10 +27,6 @@ import { Util } from "../src/util"; const expect = Chai.expect; -// const DiscordClientFactory = Proxyquire("../src/clientfactory", { -// "discord.js": { Client: require("./mocks/discordclient").MockDiscordClient }, -// }).DiscordClientFactory; - const RoomHandler = (Proxyquire("../src/matrixroomhandler", { "./util": { Util: { @@ -112,6 +102,7 @@ function createRH(opts: any = {}) { OnUpdate: async () => { }, }; const bot = { + BotUserId: "@botuser:localhost", ChannelSyncroniser: cs, GetBotId: () => "bot12345", GetChannelFromRoomId: async (roomid: string) => { @@ -194,8 +185,7 @@ function createRH(opts: any = {}) { } }, }; - const handler = new RoomHandler(bot as any, config, "@botuser:localhost", provisioner as any); - handler.setBridge(bridge, { + const store = { getEntriesByMatrixId: (matrixId) => { return [{ matrix: {}, @@ -208,7 +198,8 @@ function createRH(opts: any = {}) { removeEntriesByMatrixRoomId: () => { }, - }); + } + const handler = new RoomHandler(bot as any, config, provisioner as any, bridge as any, store); return handler; } diff --git a/test/test_provisioner.ts b/test/test_provisioner.ts index 2d9b9161cd030ece325f6baf1c50ac164013a42b..79f8f71734c2f3da382bd6a8c2093c4f7c90f235 100644 --- a/test/test_provisioner.ts +++ b/test/test_provisioner.ts @@ -29,7 +29,7 @@ const TIMEOUT_MS = 1000; describe("Provisioner", () => { describe("AskBridgePermission", () => { it("should fail to bridge a room that timed out", async () => { - const p = new Provisioner(); + const p = new Provisioner({} as any); const startAt = Date.now(); try { await p.AskBridgePermission( @@ -47,7 +47,7 @@ describe("Provisioner", () => { } }); it("should fail to bridge a room that was declined", async () => { - const p = new Provisioner(); + const p = new Provisioner({} as any); const promise = p.AskBridgePermission( new MockChannel("foo", "bar") as any, "Mark", @@ -63,7 +63,7 @@ describe("Provisioner", () => { }); it("should bridge a room that was approved", async () => { - const p = new Provisioner(); + const p = new Provisioner({} as any); const promise = p.AskBridgePermission( new MockChannel("foo", "bar") as any, "Mark", diff --git a/tools/chanfix.ts b/tools/chanfix.ts index ac39a9787f35118838f10abec7f3e64f06d73996..b37b0fe9a35fdc892ed37118e19108497c359612 100644 --- a/tools/chanfix.ts +++ b/tools/chanfix.ts @@ -80,9 +80,8 @@ const clientFactory = new ClientFactory({ token: registration.as_token, url: config.bridge.homeserverUrl, }); -const provisioner = new Provisioner(); const discordstore = new DiscordStore(config.database ? config.database.filename : "discord.db"); -const discordbot = new DiscordBot(config, discordstore, provisioner); +const discordbot = new DiscordBot("", config, null, discordstore); const bridge = new Bridge({ clientFactory, @@ -101,11 +100,9 @@ const bridge = new Bridge({ userStore: config.database.userStorePath, }); -discordbot.setBridge(bridge); - async function run() { + await bridge.loadDatabases(); await discordstore.init(); - provisioner.setStore(discordstore.roomStore); bridge._clientFactory = clientFactory; bridge._botClient = bridge._clientFactory.getClientAs(); bridge._botIntent = new Intent(bridge._botClient, bridge._botClient, { registered: true }); @@ -113,23 +110,22 @@ async function run() { const client = await discordbot.ClientFactory.getClient(); // first set update_icon to true if needed - // first set update_icon to true if needed - const mxRoomEntries = await discordstore.roomStore.getEntriesByRemoteRoomData({ + const mxRoomEntries = await bridge.getRoomStore().getEntriesByRemoteRoomData({ update_name: true, update_topic: true, }); const promiseList: Promise<void>[] = []; mxRoomEntries.forEach((entry) => { - if (entry.remote && entry.remote.get("plumbed")) { + if (entry.remote.get("plumbed")) { return; // skipping plumbed rooms } - const updateIcon = entry.remote!.get("update_icon"); + const updateIcon = entry.remote.get("update_icon"); if (updateIcon !== undefined && updateIcon !== null) { return; // skipping because something was set manually } - entry.remote!.set("update_icon", true); - promiseList.push(discordstore.roomStore.upsertEntry(entry)); + entry.remote.set("update_icon", true); + promiseList.push(bridge.getRoomStore().upsertEntry(entry)); }); await Promise.all(promiseList); diff --git a/tools/ghostfix.ts b/tools/ghostfix.ts index 2da601b3246da84cd53d531daeee9737c0d23786..3e9a4ced371aba06b27820ba0b2c945b7ae85499 100644 --- a/tools/ghostfix.ts +++ b/tools/ghostfix.ts @@ -20,15 +20,11 @@ import * as fs from "fs"; import * as args from "command-line-args"; import * as usage from "command-line-usage"; import * as Bluebird from "bluebird"; -import { ChannelSyncroniser } from "../src/channelsyncroniser"; import { DiscordBridgeConfig } from "../src/config"; -import { DiscordBot } from "../src/bot"; -import { DiscordStore } from "../src/store"; -import { Provisioner } from "../src/provisioner"; -import { UserSyncroniser } from "../src/usersyncroniser"; import { Log } from "../src/log"; import { Util } from "../src/util"; -import { TextChannel } from "discord.js"; +import { DiscordBot } from "../src/bot"; +import { DiscordStore } from "../src/store"; const log = new Log("GhostFix"); @@ -93,9 +89,6 @@ const clientFactory = new ClientFactory({ token: registration.as_token, url: config.bridge.homeserverUrl, }); -const provisioner = new Provisioner(); -const discordstore = new DiscordStore(config.database ? config.database.filename : "discord.db"); -const discordbot = new DiscordBot(config, discordstore, provisioner); const bridge = new Bridge({ clientFactory, @@ -113,14 +106,13 @@ const bridge = new Bridge({ roomStore: config.database.roomStorePath, userStore: config.database.userStorePath, }); -discordbot.setBridge(bridge); async function run() { - await discordstore.init(); - provisioner.setStore(discordstore.roomStore); - const userSync = new UserSyncroniser(bridge, config, discordbot); + await bridge.loadDatabases(); + const store = new DiscordStore(config.database); + const discordbot = new DiscordBot(botUserId, config, bridge, store); + await discordbot.init(); bridge._clientFactory = clientFactory; - await discordbot.ClientFactory.init(); const client = await discordbot.ClientFactory.getClient(); const promiseList: Promise<void>[] = []; @@ -136,7 +128,7 @@ async function run() { let currentSchedule = JOIN_ROOM_SCHEDULE[0]; const doJoin = async () => { await Util.DelayedPromise(currentSchedule); - await userSync.OnUpdateGuildMember(member, true); + await discordbot.UserSyncroniser.OnUpdateGuildMember(member, true); }; const errorHandler = async (err) => { log.error(`Error joining rooms for ${member.id}`);