From d96388f65eb927ccf3c68c9649202ca20084569d Mon Sep 17 00:00:00 2001
From: Christian Paul <christianp@matrix.org>
Date: Thu, 7 Jan 2021 12:47:52 +0100
Subject: [PATCH] Add limits.roomCount

---
 config/config.sample.yaml   | 2 ++
 config/config.schema.yaml   | 2 ++
 src/config.ts               | 1 +
 src/matrixcommandhandler.ts | 8 ++++++++
 src/provisioner.ts          | 9 +++++++++
 5 files changed, 22 insertions(+)

diff --git a/config/config.sample.yaml b/config/config.sample.yaml
index 43d5913..4039506 100644
--- a/config/config.sample.yaml
+++ b/config/config.sample.yaml
@@ -102,6 +102,8 @@ limits:
     # echos = (Copies of a sent message may arrive from discord before we've
     # fininished handling it, causing us to echo it back to the room)
     discordSendDelay: 1500
+    # Set a maximum of rooms to be bridged.
+    # roomCount: 20
 ghosts:
     # Pattern for the ghosts nick, available is :nick, :username, :tag and :id
     nickPattern: ":nick"
diff --git a/config/config.schema.yaml b/config/config.schema.yaml
index 1a2381c..9409bab 100644
--- a/config/config.schema.yaml
+++ b/config/config.schema.yaml
@@ -97,6 +97,8 @@ properties:
                 type: "number"
             discordSendDelay:
                 type: "number"
+            roomCount:
+                type: "number"
     channel:
         type: "object"
         properties:
diff --git a/src/config.ts b/src/config.ts
index 3747e66..0d49c57 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -141,6 +141,7 @@ export class DiscordBridgeConfigChannelDeleteOptions {
 class DiscordBridgeConfigLimits {
     public roomGhostJoinDelay: number = 6000;
     public discordSendDelay: number = 1500;
+    public roomCount: number = -1;
 }
 
 export class LoggingFile {
diff --git a/src/matrixcommandhandler.ts b/src/matrixcommandhandler.ts
index 61cedf6..da9d97f 100644
--- a/src/matrixcommandhandler.ts
+++ b/src/matrixcommandhandler.ts
@@ -84,6 +84,14 @@ export class MatrixCommandHandler {
                     if (!guildId || !channelId) {
                         return "Invalid syntax. For more information try `!discord help bridge`";
                     }
+                    if (await this.provisioner.RoomCountLimitReached(this.config.limits.roomCount)) {
+                        log.info(`Room count limit (value: ${this.config.limits.roomCount}) reached: Rejecting command to bridge new matrix room ${event.room_id} to ${guildId}/${channelId}`);
+                        await this.bridge.botIntent.sendText(
+                            event.room_id,
+                            `This bridge has reached its room limit of ${this.config.limits.roomCount}. Unbridge another room to allow for new connections.`,
+                            "m.notice",
+                        );
+                    }
                     try {
                         const discordResult = await this.discord.LookupRoom(guildId, channelId);
                         const channel = discordResult.channel as Discord.TextChannel;
diff --git a/src/provisioner.ts b/src/provisioner.ts
index 54de31d..50c3fec 100644
--- a/src/provisioner.ts
+++ b/src/provisioner.ts
@@ -40,6 +40,15 @@ export class Provisioner {
         return this.roomStore.linkRooms(local, remote);
     }
 
+    /**
+     * Returns if the room count limit has been reached.
+     * This can be set by the bridge admin and prevents new rooms from being bridged.
+     * @returns Has the limit been reached?
+     */
+    public async RoomCountLimitReached(limit: number): Promise<boolean> {
+        return limit >= 0 || limit >= await this.roomStore.countEntries();
+    }
+
     public async UnbridgeChannel(channel: Discord.TextChannel, rId?: string) {
         const roomsRes = await this.roomStore.getEntriesByRemoteRoomData({
             discord_channel: channel.id,
-- 
GitLab