11import { getLogger } from "../logging" ;
22import { IrcBridge } from "./IrcBridge" ;
3- import { BridgeRequest } from "../models/BridgeRequest" ;
3+ import { BridgeRequest , BridgeRequestErr } from "../models/BridgeRequest" ;
44import { IrcServer } from "../irc/IrcServer" ;
55import { MatrixRoom , PowerLevelContent } from "matrix-appservice-bridge" ;
66import { BridgedClientStatus } from "../irc/BridgedClient" ;
@@ -50,8 +50,7 @@ export class RoomAccessSyncer {
5050 constructor ( private ircBridge : IrcBridge ) { }
5151
5252 get powerLevelGracePeriod ( ) {
53- const configPeriod = this . ircBridge . config . ircService . ircHandler ?. powerLevelGracePeriodMs ;
54- return configPeriod === undefined ? DEFAULT_POWER_LEVEL_GRACE_MS : configPeriod ;
53+ return this . ircBridge . config . ircService . ircHandler ?. powerLevelGracePeriodMs ?? DEFAULT_POWER_LEVEL_GRACE_MS ;
5554 }
5655
5756 /**
@@ -202,7 +201,7 @@ export class RoomAccessSyncer {
202201 * @param {string|null } arg This is usually the affected user, if applicable.
203202 */
204203 public async onMode ( req : BridgeRequest , server : IrcServer , channel : string , by : string ,
205- mode : string , enabled : boolean , arg : string | null ) {
204+ mode : string , enabled : boolean , arg : string | null ) : Promise < BridgeRequestErr | undefined > {
206205 if ( PRIVATE_MODES . includes ( mode ) ) {
207206 await this . onPrivateMode ( req , server , channel , mode , enabled ) ;
208207 return ;
@@ -215,7 +214,8 @@ export class RoomAccessSyncer {
215214
216215 // Bridge usermodes to power levels
217216 const modeToPower = server . getModePowerMap ( ) ;
218- if ( ! Object . keys ( modeToPower ) . includes ( mode ) ) {
217+ if ( mode in modeToPower === false ) {
218+ req . log . debug ( `Mode '${ mode } ' is not known` ) ;
219219 // Not an operator power mode
220220 return ;
221221 }
@@ -226,7 +226,7 @@ export class RoomAccessSyncer {
226226 ) ;
227227 if ( matrixRooms . length === 0 ) {
228228 req . log . info ( "No mapped matrix rooms for IRC channel %s" , channel ) ;
229- return ;
229+ return BridgeRequestErr . ERR_NOT_MAPPED ;
230230 }
231231
232232 // Work out what power levels to give
@@ -243,12 +243,17 @@ export class RoomAccessSyncer {
243243 userId = bridgedClient . userId ;
244244 if ( bridgedClient . status !== BridgedClientStatus . CONNECTED ) {
245245 req . log . info ( `Bridged client for ${ nick } has no IRC client.` ) ;
246- return ;
246+ return BridgeRequestErr . ERR_DROPPED ;
247247 }
248- const userPrefixes = bridgedClient . chanData ( channel ) ?. users . get ( nick ) ;
249- if ( ! userPrefixes ) {
250- req . log . error ( `No channel data for ${ channel } /${ nick } ` ) ;
251- return ;
248+ const chanData = bridgedClient . chanData ( channel ) ;
249+ if ( ! chanData ) {
250+ req . log . error ( `No channel data for ${ channel } ` ) ;
251+ return BridgeRequestErr . ERR_DROPPED ;
252+ }
253+ const userPrefixes = chanData . users . get ( nick ) ;
254+ if ( userPrefixes === undefined ) {
255+ req . log . error ( `No channel data for ${ channel } /${ nick } . Is the user still joined to the channel?` ) ;
256+ return BridgeRequestErr . ERR_DROPPED ;
252257 }
253258 userPrefixes . split ( '' ) . forEach (
254259 prefix => {
@@ -266,7 +271,8 @@ export class RoomAccessSyncer {
266271
267272 if ( userId === null ) {
268273 // Probably the BridgeBot or a user we don't know about, drop it.
269- return ;
274+ req . log . info ( 'Could not determine userId for mode, ignoring' ) ;
275+ return BridgeRequestErr . ERR_DROPPED ;
270276 }
271277
272278 // By default, unset the user's power level. This will be treated
@@ -283,8 +289,10 @@ export class RoomAccessSyncer {
283289 `${ enabled ? level : 0 } to ${ userId } `
284290 ) ;
285291
292+ let failureCause : Error | undefined ;
286293 for ( const room of matrixRooms ) {
287- const powerLevelMap = await ( this . getCurrentPowerlevels ( room . getId ( ) ) ) || { } ;
294+ const roomId = room . getId ( ) ;
295+ const powerLevelMap = await ( this . getCurrentPowerlevels ( roomId ) ) || { } ;
288296 const users = ( powerLevelMap . users || { } ) as { [ userId : string ] : number } ;
289297
290298 // If the user's present PL is equal to the level,
@@ -310,9 +318,20 @@ export class RoomAccessSyncer {
310318 // set of modes.
311319 level = 0 ;
312320 }
313- this . setPowerLevel ( room . getId ( ) , userId , level , req ) ;
321+ try {
322+ req . log . info ( `Granting PL${ level } to ${ userId } in ${ roomId } ` ) ;
323+ await this . setPowerLevel ( roomId , userId , level , req ) ;
324+ }
325+ catch ( ex ) {
326+ req . log . warn ( `Failed to grant PL in ${ roomId } ` , ex ) ;
327+ failureCause = ex ;
328+ }
329+ }
330+ if ( failureCause ) {
331+ // There *can* be multiple failures, but just use the first one.
332+ // We still log all failures above.
333+ throw new Error ( 'Failed to update PL in some rooms' , { cause : failureCause } ) ;
314334 }
315-
316335 }
317336 /**
318337 * Called when an IRC server responds to a mode request.
0 commit comments