import { OBSWebsocketRequests , OBSWebsocketResponses , OBSWebsocketStatuses , } from "./types" ; import { sha256 } from "../utils/crypto" ; import { EventEmitter } from "../utils/EventEmitter" ; let messageId = 1 ; function generateMessageId ( ) { return messageId ++ ; } export class OBSWebsocket extends EventEmitter { private ws ! : WebSocket ; private messageCallbacks : { [ key ] : Function ; } = { } ; connect ( host = "localhost:4444" , password = "" ) { const self = this ; return new Promise < void > ( function ( resolve , reject ) { self . ws = new WebSocket ( `ws://${ host }` ) ; self . ws . onopen = ( ) => { self . send ( "GetAuthRequired" , { } , function ( data ) { const secretString = password + data . salt ; const secret = btoa ( sha256 ( secretString ) ) ; const auth = btoa ( sha256 ( secret + data . challenge ) ) ; self . send ( "Authenticate" , { auth } , ( data ) => { if ( data . status === OBSWebsocketStatuses . ERROR ) { reject ( data . error ) ; } resolve ( ) ; } ) ; } ) ; } ; self . ws . onerror = ( evt ) => { reject ( evt ) ; self . emit ( "Error" , evt ) ; } ; self . ws . onmessage = ( evt ) => { const data = JSON . parse ( evt . data ) ; const callback = self . messageCallbacks [ data [ "message-id" ] ] ; if ( callback ) { callback ( data ) ; } if ( data [ "update-type" ] ) { self . emit ( data [ "update-type" ] , data ) ; } } ; } ) ; } on < K extends keyof OBSWebsocketResponses > ( name , callback ) { return super . on ( name , callback ) ; } send < K extends keyof OBSWebsocketRequests > ( request , data ? , callback ? ) { const messageId = generateMessageId ( ) ; if ( callback ) { this . messageCallbacks [ messageId ] = callback ; } this . ws . send ( JSON . stringify ( { "request-type" : request , "message-id" : messageId . toString ( ) , ... data , } ) ) ; } close ( ) { this . ws . close ( ) ; } destroy ( ) { this . close ( ) ; super . destroy ( ) ; } }