diff --git a/src/IRCBridge.ts b/src/IRCBridge.ts index dc02055..439c2dc 100644 --- a/src/IRCBridge.ts +++ b/src/IRCBridge.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {LogService, MatrixClient, MatrixEvent} from "matrix-bot-sdk"; +import { LogService, MatrixClient, MatrixEvent } from "matrix-bot-sdk"; import * as irc from "irc-upd"; import { Auditorium } from "./models/Auditorium"; import { InterestRoom } from "./models/InterestRoom"; @@ -62,7 +62,7 @@ export class IRCBridge { } public async deriveChannelName(auditorium: Auditorium) { - const name = await auditorium.getName(); + const name = await auditorium.getSlug(); if (!name) { throw Error('Auditorium name is empty'); } @@ -93,9 +93,13 @@ export class IRCBridge { } else { this.botRoomId = data.roomId; } - - // This should timeout if the connection is broken - await this.executeCommand("bridgeversion"); + + try { + // This should timeout if the connection is broken + await this.executeCommand("bridgeversion"); + } catch (ex) { + LogService.warn(`IRCBridge`, "Failed to get IRC bridge version, it may be unreachable."); + } this.ircClient = new irc.Client(this.config.serverName, this.config.botNick, { port: this.config.port, @@ -134,6 +138,10 @@ export class IRCBridge { await this.ircClient.join(channel); const result = await this.executeCommand(`plumb ${roomId} ${this.config.serverName} ${channel}`); const resultText = result.content.body; + if (resultText.match(/Room mapping already exists/)) { + // Already bridged + return; + } if (resultText !== 'Room plumbed.') { throw Error(`IRC bridge gave an error: ${resultText}`); } diff --git a/src/commands/IrcPlumbCommand.ts b/src/commands/IrcPlumbCommand.ts index 322459e..9fcf80e 100644 --- a/src/commands/IrcPlumbCommand.ts +++ b/src/commands/IrcPlumbCommand.ts @@ -21,8 +21,9 @@ import { IRCBridge } from "../IRCBridge"; import { logMessage } from "../LogProxy"; import { KickPowerLevel } from "../models/room_kinds"; import { ConferenceMatrixClient } from "../ConferenceMatrixClient"; +import { PowerLevelAction } from "matrix-bot-sdk/lib/models/PowerLevelAction"; -const PLUMB_WAIT_MS = 1000; +const PLUMB_WAIT_MS = 10000; export class IrcPlumbCommand implements ICommand { public readonly prefixes = ["plumb-irc"]; @@ -34,7 +35,7 @@ export class IrcPlumbCommand implements ICommand { for (const auditorium of this.conference.storedAuditoriums) { const channelName = await this.ircBridge.deriveChannelName(auditorium); try { - await this.plumbOne(this.client, channelName, auditorium.roomId); + await this.plumbOne(this.client, auditorium.roomId, channelName); // Wait before plumbing the next one so as to not overwhelm the poor bridge. await new Promise(r => setTimeout(r, PLUMB_WAIT_MS)); } catch (ex) { @@ -45,7 +46,7 @@ export class IrcPlumbCommand implements ICommand { for (const interest of this.conference.storedInterestRooms) { const channelName = await this.ircBridge.deriveChannelNameSI(interest); try { - await this.plumbOne(this.client, channelName, interest.roomId); + await this.plumbOne(this.client, interest.roomId, channelName); // Wait before plumbing the next one so as to not overwhelm the poor bridge. await new Promise(r => setTimeout(r, PLUMB_WAIT_MS)); } catch (ex) { @@ -71,8 +72,10 @@ export class IrcPlumbCommand implements ICommand { } try { - // The bridge needs the ability to kick KLINED users. - await client.setUserPowerLevel(this.ircBridge.botUserId, resolvedRoomId, KickPowerLevel); + if (!await client.userHasPowerLevelForAction(this.ircBridge.botUserId, resolvedRoomId, PowerLevelAction.Kick)) { + // The bridge needs the ability to kick KLINED users. + await client.setUserPowerLevel(this.ircBridge.botUserId, resolvedRoomId, KickPowerLevel); + } } catch (ex) { LogService.warn("IrcPlumbCommand", ex); return logMessage(LogLevel.WARN, "IrcPlumbCommand", `Could not plumb channel to room ${resolvedRoomId}: could not set AS power level`, this.client);