mirror of
				https://github.com/DerTyp7/react-teamspeak-remote-app-api.git
				synced 2025-10-30 13:17:15 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			139 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { IAuthSenderPayload, IChannel, IClient, IConnection, ITS5ConnectionHandler, ITS5DataHandler, ITS5MessageHandler } from "interfaces/teamspeak";
 | |
| import { TS5DataHandler } from "handlers/teamspeak/dataHandler";
 | |
| import { TS5MessageHandler } from "handlers/teamspeak/messageHandler";
 | |
| import { ILogger } from "utils/logger";
 | |
| import { ITSRemoteAppAuthPayloadOptions } from "interfaces/api";
 | |
| 
 | |
| 
 | |
| // Establish connection to TS5 client
 | |
| // Main class
 | |
| export class TS5ConnectionHandler implements ITS5ConnectionHandler {
 | |
|   ws: WebSocket; // Websocket connection to TS5 client
 | |
|   authenticated = false; // Is the connection authenticated?
 | |
|   remoteAppPort: number; // Port of TS5 client
 | |
|   logger: ILogger; // Logger
 | |
|   authPayload: ITSRemoteAppAuthPayloadOptions; // Authentication payload
 | |
|   dataHandler: ITS5DataHandler; // Handles data/lists and states
 | |
|   messageHandler: ITS5MessageHandler; // Handles messages received from TS5 client
 | |
| 
 | |
|   constructor(
 | |
|     // Port of TS5 client
 | |
|     remoteAppPort: number,
 | |
|     authPayload: ITSRemoteAppAuthPayloadOptions,
 | |
|     logger: ILogger,
 | |
|     // State setters for dataHandler
 | |
|     setConnections: React.Dispatch<React.SetStateAction<IConnection[]>>,
 | |
|     setChannels: React.Dispatch<React.SetStateAction<IChannel[]>>,
 | |
|     setClients: React.Dispatch<React.SetStateAction<IClient[]>>,
 | |
|     setActiveConnectionStateId: React.Dispatch<React.SetStateAction<number>>,
 | |
|   ) {
 | |
| 
 | |
| 
 | |
|     // Create websocket connection to TS5 client
 | |
|     this.remoteAppPort = remoteAppPort;
 | |
|     this.authPayload = authPayload;
 | |
|     this.logger = logger;
 | |
|     this.ws = new WebSocket(`ws://localhost:${this.remoteAppPort}`);
 | |
| 
 | |
|     // Create dataHandler and messageHandler
 | |
|     this.dataHandler = new TS5DataHandler(setConnections, setChannels, setClients, logger);
 | |
|     this.messageHandler = new TS5MessageHandler(this.ws, this.dataHandler, setActiveConnectionStateId, logger);
 | |
|   }
 | |
| 
 | |
|   reconnect() {
 | |
|     this.logger.log("Reconnecting...")
 | |
|     this.ws.close();
 | |
| 
 | |
|     this.ws = new WebSocket(`ws://localhost:${this.remoteAppPort}`);
 | |
| 
 | |
|     this.dataHandler.clearAll();
 | |
|     this.authenticated = false;
 | |
|     this.connect();
 | |
|   }
 | |
| 
 | |
|   // Connect to TS5 client
 | |
|   connect() {
 | |
|     this.logger.log('Connecting to TS5 client...');
 | |
| 
 | |
|     // Create authentication payload
 | |
|     const initialPayload: IAuthSenderPayload = {
 | |
|       type: "auth",
 | |
|       payload: {
 | |
|         ...this.authPayload,
 | |
|         content: {
 | |
|           apiKey: localStorage.getItem("apiKey") ?? "",
 | |
|         },
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     this.ws.onopen = () => {
 | |
|       // Send authentication payload to TS5 client
 | |
|       this.ws.send(JSON.stringify(initialPayload));
 | |
|       this.logger.wsSent(initialPayload);
 | |
|     };
 | |
| 
 | |
|     this.ws.onclose = (event) => {
 | |
|       this.logger.log("WebSocket connection closed", event);
 | |
| 
 | |
|       // If the connection was closed before authentication, remove the API key from local storage
 | |
|       // OBS weirdly caches the localstorage and is very stubborn about clearing it (even when clicking "Clear Cache")
 | |
|       if (!this.authenticated) {
 | |
|         this.logger.log("WebSocket connection closed before authentication");
 | |
|         localStorage.removeItem("apiKey");
 | |
|       }
 | |
| 
 | |
|       setTimeout(() => {
 | |
|         this.reconnect();
 | |
|       }, 2000);
 | |
|     };
 | |
| 
 | |
|     // Handle messages received from TS5 client
 | |
|     // See TS5MessageHandler class
 | |
|     this.ws.onmessage = (event) => {
 | |
|       const data = JSON.parse(event.data);
 | |
| 
 | |
|       this.logger.wsReceived(data)
 | |
| 
 | |
|       switch (data.type) {
 | |
|         case "auth":
 | |
|           this.messageHandler.handleAuthMessage(data);
 | |
|           this.authenticated = true;
 | |
|           break;
 | |
|         case "clientMoved":
 | |
|           this.messageHandler.handleClientMovedMessage(data);
 | |
|           break;
 | |
|         case "clientPropertiesUpdated":
 | |
|           this.messageHandler.handleClientPropertiesUpdatedMessage(data);
 | |
|           break;
 | |
|         case "talkStatusChanged":
 | |
|           this.messageHandler.handleTalkStatusChangedMessage(data);
 | |
|           break;
 | |
|         case "serverPropertiesUpdated":
 | |
|           this.messageHandler.handleServerPropertiesUpdatedMessage(data);
 | |
|           break;
 | |
|         case "connectStatusChanged":
 | |
|           this.messageHandler.handleConnectStatusChangedMessage(data);
 | |
|           break;
 | |
|         case "clientSelfPropertyUpdated":
 | |
|           this.messageHandler.handleClientSelfPropertyUpdatedMessage(data);
 | |
|           break;
 | |
|         case "channels":
 | |
|           this.messageHandler.handleChannelsMessage(data);
 | |
|           break;
 | |
|         case "channelCreated":
 | |
|           this.messageHandler.handleChannelCreatedMessage(data);
 | |
|           break;
 | |
|         default:
 | |
|           this.logger.log(`No handler for event type: ${data.type}`);
 | |
|           break;
 | |
|       }
 | |
|     };
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |