import { Appservice } from "matrix-bot-sdk" ; import { Main } from "../../Main" ; import { BridgeError } from "../../bridging" ; import { Config } from "../../Config" ; import { MxEvents } from "../../minecraft" ; /**
 * This class handles all the commands on the Matrix side a user can use
 * "!minecraft" to interact with the bot and establish a bridge.
 */ export class CmdManager { public static readonly prefix = "!minecraft" ; private static readonly help = "Command List:\n" + " - bridge <room ID>: This will provide an access token to give a" + " Minecraft server to send and retrieve messages in the room with.\n" + " - unbridge [<room ID>]: This will forcefully invalidate any tokens" + " corresponding with this room\n" + ' - announce <...announcement>: This will send an announcement as' + ' "Server". Send this command in a bridged room.' ; private readonly appservice : Appservice ; private readonly main : Main ; private readonly config : Config ; constructor ( appservice , main , config ) { this . appservice = appservice ; this . main = main ; this . config = config ; } param { string } room param { string } sender param { string } body public async onMxMessage ( room , sender , body ) { const args = body . split ( ' ' ) ; const client = this . appservice . botClient ; switch ( args [ 1 ] ) { case 'bridge' : await this . bridge ( room , sender , args ) ; break ; case 'unbridge' : await this . unbridge ( room , sender , args ) ; break ; case 'announce' : const announcement = body . substr ( CmdManager . prefix . length + " announce" . length ) ; await this . announce ( room , sender , announcement ) ; break ; default : await client . sendNotice ( room , CmdManager . help ) ; } } param { string } user returns { boolean } private checkWhitelist ( user ) { return ! this . config . appservice . userWhitelist || this . config . appservice . userWhitelist . length == 0 || this . config . appservice . userWhitelist . includes ( user ) ; } param { string } room param { string } target param { string } user returns { Promise < boolean > } private async checkPrivilege ( room , target , user ) { const client = this . appservice . botClient ; const powerLevels = await client . getRoomStateEvent ( target , 'm.room.power_levels' , '' ) ; const stateEventPower = powerLevels [ 'state_default' ] || 50 ; const senderPower = powerLevels [ 'users' ] [ user ] || 0 ; const hasPerms = ( senderPower >= stateEventPower ) ; if ( ! hasPerms ) { await client . sendNotice ( room , `You need a higher power level (<${ stateEventPower })` ) ; } return hasPerms ; } param { string } room param { any } err private async bridgeError ( room , err ) { const client = this . appservice . botClient ; if ( err instanceof BridgeError . BridgedAlreadyError ) { await client . sendNotice ( room , "This room is already bridged to a server." ) ; } else if ( err instanceof Error ) { if ( err . message == 'Invalid room ID or alias' ) { await client . sendNotice ( room , CmdManager . help ) ; } else { await client . sendNotice ( room , "Something went wrong: " + err . message ) ; } } else if ( err instanceof Object && err . body instanceof Object && typeof err . body . error === 'string' ) { await client . sendNotice ( room , 'Something went wrong: ' + err . body . error ) ; } else { await client . sendNotice ( room , 'Something went wrong' ) ; } } param { string } room param { string } sender param { string } body private async announce ( room , sender , body ) { const client = this . appservice . botClient ; const hasPerms = await this . checkPrivilege ( room , room , sender ) ; if ( ! hasPerms ) { return ; } const isBridged = await this . main . bridges . isRoomBridged ( room ) ; if ( isBridged ) { this . main . sendToMinecraft ( { room : room , sender , body : `[Server] ${ body }` , event : < MxEvents . AnnounceMessageEvent > { sender : { mxid : sender , displayName : sender } , type : "message.announce" , body : body , } as MxEvents . Event } ) ; await client . sendNotice ( room , "Sent!" ) ; } else { await client . sendNotice ( room , "This room isn't bridged." ) ; } } param { string } room param { string } sender param { string [ ] } args returns { Promise < void > } private async bridge ( room , sender , args ) { const client = this . appservice . botClient ; if ( ! this . checkWhitelist ( sender ) ) { await client . sendNotice ( room , "You are not whitelisted in the bridge config" ) ; return ; } try { const target = await client . resolveRoom ( args [ 2 ] || '' ) ; const joinedRoomIds = await client . getJoinedRooms ( ) ; if ( joinedRoomIds . indexOf ( target ) === - 1 ) { const userId = await client . getUserId ( ) ; await client . sendNotice ( room , 'Bridge bot is not in that room. ' + `Please invite ${ userId } to the room and try again.` ) ; return ; } const hasPerms = await this . checkPrivilege ( room , target , sender ) ; if ( hasPerms ) { const bridge = this . main . bridges . bridge ( target ) ; await client . sendNotice ( room , 'Bridged! Go-to the Minecraft server and execute' + `"/bridge <token>"\n${ bridge . id }` ) ; } } catch ( err ) { await this . bridgeError ( room , err ) ; } } param { string } room param { string } sender param { string [ ] } args returns { Promise < void > } private async unbridge ( room , sender , args ) { const client = this . appservice . botClient ; try { const target = await client . resolveRoom ( args [ 2 ] || room ) ; const hasPerms = await this . checkPrivilege ( room , target , sender ) ; if ( hasPerms ) { const unbridged = this . main . bridges . unbridge ( target ) ; if ( unbridged ) await client . sendNotice ( room , "Room has been unbridged." ) ; else await client . sendNotice ( room , "The room was never bridged." ) ; } } catch ( err ) { await this . bridgeError ( room , err ) ; } } }