From cc745baad6a8c07e77a92e00de79e2b728b4553c Mon Sep 17 00:00:00 2001 From: Andreas Aronsson Date: Thu, 1 Aug 2024 23:29:47 +0200 Subject: [PATCH] Update Pipe to support OpenVROverlayPipe v4.0.0 --- app/src/Shared/Bot/MainController.ts | 2 +- app/src/Shared/Classes/OBS.ts | 4 +- app/src/Shared/Classes/OpenVR2WS.ts | 2 +- app/src/Shared/Classes/Pipe.ts | 76 ++++++++++++++----- .../Shared/Objects/Data/Config/ConfigPipe.ts | 9 ++- app/src/Shared/Utils/Utils.ts | 2 +- 6 files changed, 67 insertions(+), 28 deletions(-) diff --git a/app/src/Shared/Bot/MainController.ts b/app/src/Shared/Bot/MainController.ts index ad36e6b..4a2cb5a 100644 --- a/app/src/Shared/Bot/MainController.ts +++ b/app/src/Shared/Bot/MainController.ts @@ -52,7 +52,7 @@ export default class MainController { const controllerConfig = await DataBaseHelper.loadMain(new ConfigController()) if(controllerConfig.useWebsockets.twitchEventSub) modules.twitchEventSub.init().then() - modules.pipe.setOverlayTitle("desbot") + modules.pipe.setOverlayTitle("desbot").then() Functions.setEmptySoundForTTS().then() diff --git a/app/src/Shared/Classes/OBS.ts b/app/src/Shared/Classes/OBS.ts index bf54beb..7a85e71 100644 --- a/app/src/Shared/Classes/OBS.ts +++ b/app/src/Shared/Classes/OBS.ts @@ -46,8 +46,8 @@ export default class OBS { } } if(opData.authentication) { - const base64secret = await Utils.sha256(this._config.password+opData.authentication.salt) - const authentication = await Utils.sha256(base64secret + opData.authentication.challenge) + const base64secret = await Utils.hashPassword(this._config.password+opData.authentication.salt) + const authentication = await Utils.hashPassword(base64secret + opData.authentication.challenge) authResponse.d.authentication = authentication } this._socket?.send(JSON.stringify(authResponse)) diff --git a/app/src/Shared/Classes/OpenVR2WS.ts b/app/src/Shared/Classes/OpenVR2WS.ts index f67bef6..7116c4d 100644 --- a/app/src/Shared/Classes/OpenVR2WS.ts +++ b/app/src/Shared/Classes/OpenVR2WS.ts @@ -21,7 +21,7 @@ export default class OpenVR2WS { async init() { // Init function as we want to set the callbacks before the first messages arrive. this._config = await DataBaseHelper.loadMain(new ConfigOpenVR2WS()) - this._password = await Utils.sha256(this._config.password) + this._password = await Utils.hashPassword(this._config.password) this._socket = new WebSockets( `ws://localhost:${this._config.port}`, 10, diff --git a/app/src/Shared/Classes/Pipe.ts b/app/src/Shared/Classes/Pipe.ts index abf2e74..c2cfc1a 100644 --- a/app/src/Shared/Classes/Pipe.ts +++ b/app/src/Shared/Classes/Pipe.ts @@ -47,13 +47,24 @@ export default class Pipe { return this._socket?.isConnected() ?? false } - setOverlayTitle(title: string) { + private async getPassword(): Promise { + return this._config.password.length > 0 ? await Utils.hashPassword(this._config.password) : '' + } + + async setOverlayTitle(title: string) { this._socket?.send(JSON.stringify({ - basicTitle: title, - basicMessage: "Initializing Overlay Pipe" + key: 'EnqueueNotification', + password: await this.getPassword(), + nonce: Utils.getNonce('DesbotPipe'), + data: { + title: title, + message: "Initializing Overlay Pipe" + } })) } + + sendBasicObj( messageData: ITwitchMessageData, userData: IActionUser, @@ -207,14 +218,22 @@ export default class Pipe { const text = displayName.length > 0 ? `${displayName}: ${cleanText}` : cleanText if(imageDataUrl != null) { this._socket?.send(JSON.stringify({ - basicTitle: "", - basicMessage: text, - imageData: Utils.removeImageHeader(imageDataUrl) + key: 'EnqueueNotification', + password: await this.getPassword(), + data: { + title: "", + message: text, + imageData: Utils.removeImageHeader(imageDataUrl) + } })) } else { this._socket?.send(JSON.stringify({ - basicTitle: "", - basicMessage: text, + key: 'EnqueueNotification', + password: await this.getPassword(), + data: { + title: "", + message: text + } })) } } @@ -223,6 +242,8 @@ export default class Pipe { async sendCustom(preset: PresetPipeCustom&AbstractData, imageData: string, durationMs: number = -1) { if(!this._socket?.isConnected()) console.warn('Pipe.sendCustom: Websockets instance not initiated.') const nonce = Utils.getNonce('custom-pipe') + + // Generate sub-items const animations: IPipeRequestCustomPropertiesAnimation[] = [] for(const animPreset of preset.animations) { animations.push({ @@ -249,11 +270,14 @@ export default class Pipe { verticalAlignment: areaPreset.alignmentHorizontally_andVertically }) } + + // Build request const message: IPipeRequest = { + key: 'EnqueueOverlay', + password: await this.getPassword(), nonce, - imageData, - customProperties: { - enabled: true, + data: { + imageData, anchorType: preset.anchorType, attachToAnchor: preset.anchorType_isAttached, ignoreAnchorYaw: preset.ignoreAnchorYaw, @@ -343,7 +367,6 @@ export default class Pipe { // If the above resulted in image data, broadcast it for(const imageB64 of imageB64arr) { if(customPreset) { - const textAreaCount = customPreset.textAreas.length const texts = ArrayUtils.getAsType(action.texts, action.texts_use) let i = 0 let text = texts[i] @@ -367,17 +390,28 @@ export default class Pipe { } } +type TPipeRequestKey = + 'EnqueueNotification' | + 'EnqueueOverlay' + interface IPipeRequest { + key: TPipeRequestKey + password: string + nonce: string + data: IPipeRequestNotification|IPipeRequestOverlay +} + +interface IPipeRequestNotification { + title: string + message: string imageData?: string imagePath?: string - nonce?: string - basicTitle?: string - basicMessage?: string - customProperties?: IPipeRequestCustomProperties } -interface IPipeRequestCustomProperties { - enabled: boolean +interface IPipeRequestOverlay { + imageData?: string + imagePath?: string + anchorType: string attachToAnchor: boolean ignoreAnchorYaw: boolean @@ -398,9 +432,9 @@ interface IPipeRequestCustomProperties { pitchDeg: number rollDeg: number - follow: IPipeRequestCustomPropertiesFollow - transitionIn: IPipeRequestCustomPropertiesTransition - transitionOut: IPipeRequestCustomPropertiesTransition + follow?: IPipeRequestCustomPropertiesFollow + transitionIn?: IPipeRequestCustomPropertiesTransition + transitionOut?: IPipeRequestCustomPropertiesTransition animations: IPipeRequestCustomPropertiesAnimation[] textAreas: IPipeRequestCustomPropertiesTextArea[] } diff --git a/app/src/Shared/Objects/Data/Config/ConfigPipe.ts b/app/src/Shared/Objects/Data/Config/ConfigPipe.ts index 15b5885..d2232e2 100644 --- a/app/src/Shared/Objects/Data/Config/ConfigPipe.ts +++ b/app/src/Shared/Objects/Data/Config/ConfigPipe.ts @@ -5,6 +5,7 @@ import ConfigImageEditorRect, {ConfigImageEditorFontSettings, ConfigImageEditorO export default class ConfigPipe extends AbstractData { port: number = 8077 + password: string = '' useCustomChatNotification: boolean = false customChatMessageConfig = new ConfigPipeCustomMessage() customChatNameConfig = new ConfigPipeCustomMessageName() @@ -14,14 +15,18 @@ export default class ConfigPipe extends AbstractData { enlist() { DataMap.addRootInstance({ instance: new ConfigPipe(), - description: 'In-VR-overlays and notifications with: https://github.com/BOLL7708/OpenVRNotificationPipe', + description: 'In-VR-overlays and notifications with: https://github.com/BOLL7708/OpenVROverlayPipe', documentation: { - port: 'The port number set in OpenVRNotificationPipe.', + port: 'The port number set in OpenVROverlayPipe.', + password: 'The optional password for OpenVROverlayPipe.', useCustomChatNotification: 'If on uses a custom notification graphic for text pipes into VR, instead of the default SteamVR notification.', customChatMessageConfig: 'The text box settings for the custom chat notification text message.', customChatNameConfig: 'The text box settings for the custom chat notification username.\nWill not be drawn if no username was supplied.', customChatAvatarConfig: 'The settings for the custom chat notification avatar image.\nWill not be drawn if the image could not be loaded.', cleanTextConfig: 'Configuration for cleaning the text before it is piped.' + }, + types: { + password: 'string|secret' } }) } diff --git a/app/src/Shared/Utils/Utils.ts b/app/src/Shared/Utils/Utils.ts index 4cb53c3..6b19409 100644 --- a/app/src/Shared/Utils/Utils.ts +++ b/app/src/Shared/Utils/Utils.ts @@ -7,7 +7,7 @@ export default class Utils { return rest ? [first, rest.join(needle)] : [first] } - static async sha256(message: string) { + static async hashPassword(message: string) { const textBuffer = new TextEncoder().encode(message); // encode as UTF-8 const hashBuffer = await crypto.subtle.digest('SHA-256', textBuffer); // hash the message const byteArray = Array.from(new Uint8Array(hashBuffer)); // convert ArrayBuffer to Array