3 Commits

Author SHA1 Message Date
Janis
7362d80a9e add option to enable logger 2023-08-03 00:12:57 +02:00
Janis
e920aa6f18 add auth options in contructor 2023-08-02 23:40:51 +02:00
Janis
9da47028bc update readme 2023-07-24 02:31:59 +02:00
9 changed files with 120 additions and 61 deletions

View File

@@ -6,6 +6,10 @@ This is a ReactJS hook for the TeamSpeak5 RemoteApp API.
It gathers all the events and methods from the API and makes them available as React states. It gathers all the events and methods from the API and makes them available as React states.
Please note that this is still a work in progress and not all events and methods are implemented yet.
Projects which are using this hook: [TS5 OBS Overlay](https://github.com/DerTyp7/ts5-obs-overlay)
## Table of Contents ## Table of Contents
- [React TeamSpeak5 RemoteApp API](#react-teamspeak5-remoteapp-api) - [React TeamSpeak5 RemoteApp API](#react-teamspeak5-remoteapp-api)

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-ts5-remote-app-api", "name": "react-ts5-remote-app-api",
"version": "1.0.5", "version": "1.1.1",
"description": "React hook/api for the TeamSpeak5 remote app feature", "description": "React hook/api for the TeamSpeak5 remote app feature",
"main": "dist/cjs/index.js", "main": "dist/cjs/index.js",
"module": "dist/esm/index.js", "module": "dist/esm/index.js",

View File

@@ -1,7 +1,8 @@
import { IAuthSenderPayload, IChannel, IClient, IConnection, ITS5ConnectionHandler, ITS5DataHandler, ITS5MessageHandler } from "../../interfaces/teamspeak"; import { IAuthSenderPayload, IChannel, IClient, IConnection, ITS5ConnectionHandler, ITS5DataHandler, ITS5MessageHandler } from "../../interfaces/teamspeak";
import { TS5DataHandler } from "./dataHandler"; import { TS5DataHandler } from "./dataHandler";
import { TS5MessageHandler } from "./messageHandler"; import { TS5MessageHandler } from "./messageHandler";
import Logger from "../../utils/logger"; import { ILogger } from "../../utils/logger";
import { ITSRemoteAppAuthPayloadOptions } from "../../interfaces/api";
// Establish connection to TS5 client // Establish connection to TS5 client
@@ -10,13 +11,16 @@ export class TS5ConnectionHandler implements ITS5ConnectionHandler {
ws: WebSocket; // Websocket connection to TS5 client ws: WebSocket; // Websocket connection to TS5 client
authenticated = false; // Is the connection authenticated? authenticated = false; // Is the connection authenticated?
remoteAppPort: number; // Port of TS5 client remoteAppPort: number; // Port of TS5 client
logger: ILogger; // Logger
authPayload: ITSRemoteAppAuthPayloadOptions; // Authentication payload
dataHandler: ITS5DataHandler; // Handles data/lists and states dataHandler: ITS5DataHandler; // Handles data/lists and states
messageHandler: ITS5MessageHandler; // Handles messages received from TS5 client messageHandler: ITS5MessageHandler; // Handles messages received from TS5 client
constructor( constructor(
// Port of TS5 client // Port of TS5 client
remoteAppPort: number, remoteAppPort: number,
authPayload: ITSRemoteAppAuthPayloadOptions,
logger: ILogger,
// State setters for dataHandler // State setters for dataHandler
setConnections: React.Dispatch<React.SetStateAction<IConnection[]>>, setConnections: React.Dispatch<React.SetStateAction<IConnection[]>>,
setChannels: React.Dispatch<React.SetStateAction<IChannel[]>>, setChannels: React.Dispatch<React.SetStateAction<IChannel[]>>,
@@ -27,15 +31,17 @@ export class TS5ConnectionHandler implements ITS5ConnectionHandler {
// Create websocket connection to TS5 client // Create websocket connection to TS5 client
this.remoteAppPort = remoteAppPort; this.remoteAppPort = remoteAppPort;
this.authPayload = authPayload;
this.logger = logger;
this.ws = new WebSocket(`ws://localhost:${this.remoteAppPort}`); this.ws = new WebSocket(`ws://localhost:${this.remoteAppPort}`);
// Create dataHandler and messageHandler // Create dataHandler and messageHandler
this.dataHandler = new TS5DataHandler(setConnections, setChannels, setClients); this.dataHandler = new TS5DataHandler(setConnections, setChannels, setClients, logger);
this.messageHandler = new TS5MessageHandler(this.ws, this.dataHandler, setActiveConnectionStateId); this.messageHandler = new TS5MessageHandler(this.ws, this.dataHandler, setActiveConnectionStateId, logger);
} }
reconnect() { reconnect() {
Logger.log("Reconnecting...") this.logger.log("Reconnecting...")
this.ws.close(); this.ws.close();
this.ws = new WebSocket(`ws://localhost:${this.remoteAppPort}`); this.ws = new WebSocket(`ws://localhost:${this.remoteAppPort}`);
@@ -47,35 +53,32 @@ export class TS5ConnectionHandler implements ITS5ConnectionHandler {
// Connect to TS5 client // Connect to TS5 client
connect() { connect() {
Logger.log('Connecting to TS5 client...'); this.logger.log('Connecting to TS5 client...');
// Create authentication payload // Create authentication payload
const initalPayload: IAuthSenderPayload = { const initalPayload: IAuthSenderPayload = {
type: "auth", type: "auth",
payload: { payload: {
identifier: "de.tealfire.obs", ...this.authPayload,
version: "1.1.3",
name: "TS5 OBS Overlay",
description: "A OBS overlay for TS5 by DerTyp876",
content: { content: {
apiKey: localStorage.getItem("apiKey") ?? "", apiKey: localStorage.getItem("apiKey") ?? "",
}, },
}, }
}; };
this.ws.onopen = () => { this.ws.onopen = () => {
// Send authentication payload to TS5 client // Send authentication payload to TS5 client
this.ws.send(JSON.stringify(initalPayload)); this.ws.send(JSON.stringify(initalPayload));
Logger.wsSent(initalPayload); this.logger.wsSent(initalPayload);
}; };
this.ws.onclose = (event) => { this.ws.onclose = (event) => {
Logger.log("WebSocket connection closed", event); this.logger.log("WebSocket connection closed", event);
// If the connection was closed before authentication, remove the API key from local storage // 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 clicken "Clear Cache") // OBS weirdly caches the localstorage and is very stubborn about clearing it (even when clicken "Clear Cache")
if (!this.authenticated) { if (!this.authenticated) {
Logger.log("WebSocket connection closed before authentication"); this.logger.log("WebSocket connection closed before authentication");
localStorage.removeItem("apiKey"); localStorage.removeItem("apiKey");
} }
@@ -89,7 +92,7 @@ export class TS5ConnectionHandler implements ITS5ConnectionHandler {
this.ws.onmessage = (event) => { this.ws.onmessage = (event) => {
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
Logger.wsReceived(data) this.logger.wsReceived(data)
switch (data.type) { switch (data.type) {
case "auth": case "auth":
@@ -118,7 +121,7 @@ export class TS5ConnectionHandler implements ITS5ConnectionHandler {
this.messageHandler.handleChannelsMessage(data); this.messageHandler.handleChannelsMessage(data);
break; break;
default: default:
Logger.log(`No handler for event type: ${data.type}`); this.logger.log(`No handler for event type: ${data.type}`);
break; break;
} }
}; };

View File

@@ -1,4 +1,4 @@
import Logger from "../..//utils/logger"; import { ILogger } from "../..//utils/logger";
import { IConnection, IChannel, IClient, ITS5DataHandler } from "../../interfaces/teamspeak"; import { IConnection, IChannel, IClient, ITS5DataHandler } from "../../interfaces/teamspeak";
@@ -18,11 +18,14 @@ export class TS5DataHandler implements ITS5DataHandler {
setChannels: React.Dispatch<React.SetStateAction<IChannel[]>>; setChannels: React.Dispatch<React.SetStateAction<IChannel[]>>;
setClients: React.Dispatch<React.SetStateAction<IClient[]>>; setClients: React.Dispatch<React.SetStateAction<IClient[]>>;
logger: ILogger;
constructor( constructor(
// State setters for App.tsx // State setters for App.tsx
setConnections: React.Dispatch<React.SetStateAction<IConnection[]>>, setConnections: React.Dispatch<React.SetStateAction<IConnection[]>>,
setChannels: React.Dispatch<React.SetStateAction<IChannel[]>>, setChannels: React.Dispatch<React.SetStateAction<IChannel[]>>,
setClients: React.Dispatch<React.SetStateAction<IClient[]>> setClients: React.Dispatch<React.SetStateAction<IClient[]>>,
logger: ILogger,
) { ) {
this.setConnections = setConnections; this.setConnections = setConnections;
this.setChannels = setChannels; this.setChannels = setChannels;
@@ -31,6 +34,8 @@ export class TS5DataHandler implements ITS5DataHandler {
this.localConnections = []; this.localConnections = [];
this.localChannels = []; this.localChannels = [];
this.localClients = []; this.localClients = [];
this.logger = logger;
} }
// Update App.tsx states // Update App.tsx states
@@ -59,88 +64,88 @@ export class TS5DataHandler implements ITS5DataHandler {
// Add data to local lists and update states // Add data to local lists and update states
addConnection(connection: IConnection) { addConnection(connection: IConnection) {
Logger.log("Adding connection...", connection) this.logger.log("Adding connection...", connection)
const existingConnection: IConnection | undefined = this.localConnections.find((localConnection: IConnection) => localConnection.id === connection.id); const existingConnection: IConnection | undefined = this.localConnections.find((localConnection: IConnection) => localConnection.id === connection.id);
if (existingConnection == undefined) { if (existingConnection == undefined) {
this.localConnections.push(connection); this.localConnections.push(connection);
this.updateConnectionsState(); this.updateConnectionsState();
Logger.log("Connection added") this.logger.log("Connection added")
} else { } else {
Logger.log("Connection already exists") this.logger.log("Connection already exists")
} }
} }
addChannel(channel: IChannel) { addChannel(channel: IChannel) {
Logger.log("Adding channel...", channel) this.logger.log("Adding channel...", channel)
const existingChannel: IChannel | undefined = this.localChannels.find((localChannel: IChannel) => localChannel.id === channel.id && localChannel.connection.id === channel.connection.id); const existingChannel: IChannel | undefined = this.localChannels.find((localChannel: IChannel) => localChannel.id === channel.id && localChannel.connection.id === channel.connection.id);
if (existingChannel == undefined) { if (existingChannel == undefined) {
this.localChannels.push(channel); this.localChannels.push(channel);
this.updateChannelsState(); this.updateChannelsState();
Logger.log("Channel added") this.logger.log("Channel added")
} else { } else {
Logger.log("Channel already exists") this.logger.log("Channel already exists")
} }
} }
addClient(client: IClient) { addClient(client: IClient) {
Logger.log("Adding client...", client) this.logger.log("Adding client...", client)
const existingClient: IClient | undefined = this.localClients.find((localClient: IClient) => localClient.id === client.id && localClient.channel?.connection.id === client.channel?.connection.id); const existingClient: IClient | undefined = this.localClients.find((localClient: IClient) => localClient.id === client.id && localClient.channel?.connection.id === client.channel?.connection.id);
if (existingClient == undefined) { if (existingClient == undefined) {
this.localClients.push(client); this.localClients.push(client);
this.updateClientsState(); this.updateClientsState();
Logger.log("Client added") this.logger.log("Client added")
} else { } else {
Logger.log("Client already exists") this.logger.log("Client already exists")
} }
} }
// Update data in local lists and update states // Update data in local lists and update states
updateConnection(connection: IConnection) { updateConnection(connection: IConnection) {
Logger.log("Updating connection...", connection) this.logger.log("Updating connection...", connection)
const existingConnection: IConnection | undefined = this.localConnections.find((localConnection: IConnection) => localConnection.id === connection.id); const existingConnection: IConnection | undefined = this.localConnections.find((localConnection: IConnection) => localConnection.id === connection.id);
if (existingConnection !== undefined) { if (existingConnection !== undefined) {
this.localConnections[this.localConnections.indexOf(existingConnection)] = connection; this.localConnections[this.localConnections.indexOf(existingConnection)] = connection;
this.updateConnectionsState(); this.updateConnectionsState();
Logger.log("Connection updated") this.logger.log("Connection updated")
} else { } else {
Logger.log("Connection does not exist") this.logger.log("Connection does not exist")
} }
} }
updateChannel(channel: IChannel) { updateChannel(channel: IChannel) {
Logger.log("Updating channel...", channel) this.logger.log("Updating channel...", channel)
const existingChannel: IChannel | undefined = this.localChannels.find((localChannel: IChannel) => localChannel.id === channel.id && localChannel.connection.id === channel.connection.id); const existingChannel: IChannel | undefined = this.localChannels.find((localChannel: IChannel) => localChannel.id === channel.id && localChannel.connection.id === channel.connection.id);
if (existingChannel !== undefined) { if (existingChannel !== undefined) {
this.localChannels[this.localChannels.indexOf(existingChannel)] = channel; this.localChannels[this.localChannels.indexOf(existingChannel)] = channel;
this.updateChannelsState(); this.updateChannelsState();
Logger.log("Channel updated") this.logger.log("Channel updated")
} else { } else {
Logger.log("Channel does not exist") this.logger.log("Channel does not exist")
} }
} }
updateClient(client: IClient) { updateClient(client: IClient) {
Logger.log("Updating client...", client) this.logger.log("Updating client...", client)
const existingClient: IClient | undefined = this.localClients.find((localClient: IClient) => localClient.id === client.id && localClient.channel?.connection.id === client.channel?.connection.id); const existingClient: IClient | undefined = this.localClients.find((localClient: IClient) => localClient.id === client.id && localClient.channel?.connection.id === client.channel?.connection.id);
if (existingClient !== undefined) { if (existingClient !== undefined) {
this.localClients[this.localClients.indexOf(existingClient)] = client; this.localClients[this.localClients.indexOf(existingClient)] = client;
this.updateClientsState(); this.updateClientsState();
Logger.log("Client updated") this.logger.log("Client updated")
} else { } else {
Logger.log("Client does not exist") this.logger.log("Client does not exist")
} }
} }
// Remove data from local lists and update states // Remove data from local lists and update states
removeConnection(connection: IConnection) { removeConnection(connection: IConnection) {
Logger.log("Removing connection...", connection) this.logger.log("Removing connection...", connection)
const existingConnection: IConnection | undefined = this.localConnections.find((localConnection: IConnection) => localConnection.id === connection.id); const existingConnection: IConnection | undefined = this.localConnections.find((localConnection: IConnection) => localConnection.id === connection.id);
if (existingConnection !== undefined) { if (existingConnection !== undefined) {
@@ -153,14 +158,14 @@ export class TS5DataHandler implements ITS5DataHandler {
this.updateChannelsState(); this.updateChannelsState();
this.updateClientsState(); this.updateClientsState();
this.updateConnectionsState(); this.updateConnectionsState();
Logger.log("Connection removed") this.logger.log("Connection removed")
} else { } else {
Logger.log("Connection does not exist") this.logger.log("Connection does not exist")
} }
} }
removeChannel(channel: IChannel) { removeChannel(channel: IChannel) {
Logger.log("Removing channel...", channel) this.logger.log("Removing channel...", channel)
const existingChannel: IChannel | undefined = this.localChannels.find((localChannel: IChannel) => localChannel.id === channel.id && localChannel.connection.id === channel.connection.id); const existingChannel: IChannel | undefined = this.localChannels.find((localChannel: IChannel) => localChannel.id === channel.id && localChannel.connection.id === channel.connection.id);
if (existingChannel !== undefined) { if (existingChannel !== undefined) {
@@ -171,22 +176,22 @@ export class TS5DataHandler implements ITS5DataHandler {
this.updateClientsState(); this.updateClientsState();
this.updateChannelsState(); this.updateChannelsState();
Logger.log("Channel removed") this.logger.log("Channel removed")
} else { } else {
Logger.log("Channel does not exist") this.logger.log("Channel does not exist")
} }
} }
removeClient(client: IClient) { removeClient(client: IClient) {
Logger.log("Removing client...", client) this.logger.log("Removing client...", client)
const existingClient: IClient | undefined = this.localClients.find((localClient: IClient) => localClient.id === client.id && localClient.channel?.connection.id === client.channel?.connection.id); const existingClient: IClient | undefined = this.localClients.find((localClient: IClient) => localClient.id === client.id && localClient.channel?.connection.id === client.channel?.connection.id);
if (existingClient !== undefined) { if (existingClient !== undefined) {
this.localClients.splice(this.localClients.indexOf(existingClient), 1); this.localClients.splice(this.localClients.indexOf(existingClient), 1);
this.updateClientsState(); this.updateClientsState();
Logger.log("Client removed") this.logger.log("Client removed")
} else { } else {
Logger.log("Client does not exist") this.logger.log("Client does not exist")
} }
} }

View File

@@ -1,18 +1,20 @@
import Logger from "../../utils/logger"; import { ILogger } from "../../utils/logger";
import { IChannelInfos, IConnection, IChannel, IAuthMessage, IClientInfo, IClientMovedMessage, IClient, IClientPropertiesUpdatedMessage, ITalkStatusChangedMessage, IClientSelfPropertyUpdatedMessage, IServerPropertiesUpdatedMessage, IConnectStatusChangedMessage, IChannelsMessage, ITS5MessageHandler, ITS5DataHandler } from "../../interfaces/teamspeak"; import { IChannelInfos, IConnection, IChannel, IAuthMessage, IClientInfo, IClientMovedMessage, IClient, IClientPropertiesUpdatedMessage, ITalkStatusChangedMessage, IClientSelfPropertyUpdatedMessage, IServerPropertiesUpdatedMessage, IConnectStatusChangedMessage, IChannelsMessage, ITS5MessageHandler, ITS5DataHandler } from "../../interfaces/teamspeak";
// Handle incoming messages from TS5 client // Handle incoming messages from TS5 client
export class TS5MessageHandler implements ITS5MessageHandler { export class TS5MessageHandler implements ITS5MessageHandler {
ws: WebSocket; ws: WebSocket;
dataHandler: ITS5DataHandler; dataHandler: ITS5DataHandler;
logger: ILogger;
setActiveConnectionStateId: React.Dispatch<React.SetStateAction<number>>; setActiveConnectionStateId: React.Dispatch<React.SetStateAction<number>>;
activeConnectionId = 0; activeConnectionId = 0;
constructor(ws: WebSocket, dataHandler: ITS5DataHandler, setActiveConnectionStateId: React.Dispatch<React.SetStateAction<number>>) { constructor(ws: WebSocket, dataHandler: ITS5DataHandler, setActiveConnectionStateId: React.Dispatch<React.SetStateAction<number>>, logger: ILogger) {
this.ws = ws; this.ws = ws;
this.dataHandler = dataHandler; this.dataHandler = dataHandler;
this.setActiveConnectionStateId = setActiveConnectionStateId; this.setActiveConnectionStateId = setActiveConnectionStateId;
this.logger = logger;
} }
setActiveConnection(connectionId: number) { setActiveConnection(connectionId: number) {
@@ -82,7 +84,7 @@ export class TS5MessageHandler implements ITS5MessageHandler {
channel: newChannel, channel: newChannel,
properties: data.payload.properties, properties: data.payload.properties,
}); });
Logger.ts(`New Client found (${data.payload.connectionId} - ${data.payload.clientId} - ${data.payload.properties.nickname})`) this.logger.ts(`New Client found (${data.payload.connectionId} - ${data.payload.clientId} - ${data.payload.properties.nickname})`)
} }
}, 2000); }, 2000);
@@ -90,7 +92,7 @@ export class TS5MessageHandler implements ITS5MessageHandler {
const newChannel: IChannel | undefined = this.dataHandler.getChannelById(data.payload.newChannelId, data.payload.connectionId); const newChannel: IChannel | undefined = this.dataHandler.getChannelById(data.payload.newChannelId, data.payload.connectionId);
if (newChannel === undefined || newChannel.id === 0) { if (newChannel === undefined || newChannel.id === 0) {
Logger.ts(`Client left (${data.payload.connectionId} - ${data.payload.clientId} - ${data.payload.properties.nickname})`) this.logger.ts(`Client left (${data.payload.connectionId} - ${data.payload.clientId} - ${data.payload.properties.nickname})`)
if (client !== undefined) { if (client !== undefined) {
this.dataHandler.removeClient(client); this.dataHandler.removeClient(client);
} }
@@ -98,7 +100,7 @@ export class TS5MessageHandler implements ITS5MessageHandler {
} }
if (client !== undefined) { // Client already exists if (client !== undefined) { // Client already exists
Logger.ts(`Client moved (${client.channel.connection.id} - ${client.id} - ${client.properties.nickname})`) this.logger.ts(`Client moved (${client.channel.connection.id} - ${client.id} - ${client.properties.nickname})`)
this.dataHandler.updateClient({ this.dataHandler.updateClient({
...client, ...client,
@@ -107,7 +109,7 @@ export class TS5MessageHandler implements ITS5MessageHandler {
} else { // Client does not exist } else { // Client does not exist
// Client joined // Client joined
Logger.ts(`Client joined (${data.payload.connectionId} - ${data.payload.clientId} - ${data.payload.properties.nickname})`) this.logger.ts(`Client joined (${data.payload.connectionId} - ${data.payload.clientId} - ${data.payload.properties.nickname})`)
this.dataHandler.addClient( this.dataHandler.addClient(
{ {

View File

@@ -1,9 +1,11 @@
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable react-hooks/exhaustive-deps */
import { TS5ConnectionHandler } from "../handlers/teamspeak/connectionHandler"; import { TS5ConnectionHandler } from "../handlers/teamspeak/connectionHandler";
import { ITSRemoteAppOptions } from "../interfaces/api";
import { IClient, IChannel, IConnection, ITS5ConnectionHandler } from "../interfaces/teamspeak"; import { IClient, IChannel, IConnection, ITS5ConnectionHandler } from "../interfaces/teamspeak";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import Logger from "../utils/logger";
export default function useTSRemoteApp({ remoteAppPort = 5899 }: { remoteAppPort: number }) { export default function useTSRemoteApp(options: ITSRemoteAppOptions) {
const [clients, setClients] = useState<IClient[]>([]); const [clients, setClients] = useState<IClient[]>([]);
const [channels, setChannels] = useState<IChannel[]>([]); const [channels, setChannels] = useState<IChannel[]>([]);
const [connections, setConnections] = useState<IConnection[]>([]); const [connections, setConnections] = useState<IConnection[]>([]);
@@ -17,7 +19,9 @@ export default function useTSRemoteApp({ remoteAppPort = 5899 }: { remoteAppPort
useEffect(() => { useEffect(() => {
const tsConnection: ITS5ConnectionHandler = new TS5ConnectionHandler( const tsConnection: ITS5ConnectionHandler = new TS5ConnectionHandler(
remoteAppPort, options.remoteAppPort ?? 5899,
options.auth,
new Logger(options.logging ?? false),
setConnections, setConnections,
setChannels, setChannels,
setClients, setClients,

12
src/interfaces/api.ts Normal file
View File

@@ -0,0 +1,12 @@
export interface ITSRemoteAppOptions {
remoteAppPort: number;
logging: boolean;
auth: ITSRemoteAppAuthPayloadOptions,
}
export interface ITSRemoteAppAuthPayloadOptions {
identifier: string,
version: string,
name: string,
description: string
}

View File

@@ -1,8 +1,13 @@
import { ILogger } from "../utils/logger";
import { ITSRemoteAppAuthPayloadOptions } from "./api";
// Classes // Classes
export interface ITS5ConnectionHandler { export interface ITS5ConnectionHandler {
ws: WebSocket; ws: WebSocket;
authenticated: boolean; authenticated: boolean;
remoteAppPort: number; remoteAppPort: number;
logger: ILogger;
authPayload: ITSRemoteAppAuthPayloadOptions;
dataHandler: ITS5DataHandler; dataHandler: ITS5DataHandler;
messageHandler: ITS5MessageHandler; messageHandler: ITS5MessageHandler;
reconnect(): void; reconnect(): void;
@@ -13,6 +18,7 @@ export interface ITS5DataHandler {
localConnections: IConnection[]; localConnections: IConnection[];
localChannels: IChannel[]; localChannels: IChannel[];
localClients: IClient[]; localClients: IClient[];
logger: ILogger;
setConnections: React.Dispatch<React.SetStateAction<IConnection[]>>; setConnections: React.Dispatch<React.SetStateAction<IConnection[]>>;
setChannels: React.Dispatch<React.SetStateAction<IChannel[]>>; setChannels: React.Dispatch<React.SetStateAction<IChannel[]>>;
setClients: React.Dispatch<React.SetStateAction<IClient[]>>; setClients: React.Dispatch<React.SetStateAction<IClient[]>>;
@@ -34,6 +40,7 @@ export interface ITS5DataHandler {
export interface ITS5MessageHandler { export interface ITS5MessageHandler {
ws: WebSocket; ws: WebSocket;
dataHandler: ITS5DataHandler; dataHandler: ITS5DataHandler;
logger: ILogger;
setActiveConnectionStateId: React.Dispatch<React.SetStateAction<number>>; setActiveConnectionStateId: React.Dispatch<React.SetStateAction<number>>;
activeConnectionId: number; activeConnectionId: number;
setActiveConnection(connectionId: number): void; setActiveConnection(connectionId: number): void;

View File

@@ -1,31 +1,53 @@
export default class Logger { export interface ILogger {
enabled: boolean;
log(message: string, data?: object | null): void;
warn(message: string, data?: object | null): void;
error(message: string, data?: object | null): void;
wsReceived(data: object, message?: string | undefined): void;
wsSent(data: object, message?: string | undefined): void;
ts(message: string, data?: object | null): void;
}
export default class Logger implements ILogger {
enabled: boolean;
constructor(enabled: boolean) {
this.enabled = enabled;
}
// Log message to the console // Log message to the console
public static log(message: string, data: object | null = null): void { public log(message: string, data: object | null = null): void {
if (!this.enabled) return;
console.log(`[Log] %c${message}`.trim(), "color: gray", data ?? ""); console.log(`[Log] %c${message}`.trim(), "color: gray", data ?? "");
} }
// Log warning to the console // Log warning to the console
public static warn(message: string, data: object | null = null): void { public warn(message: string, data: object | null = null): void {
if (!this.enabled) return;
console.warn(`%c${message}`.trim(), data ?? ""); console.warn(`%c${message}`.trim(), data ?? "");
} }
// Log error to the console // Log error to the console
public static error(message: string, data: object | null = null): void { public error(message: string, data: object | null = null): void {
if (!this.enabled) return;
console.error(`%c${message}`.trim(), data ?? ""); console.error(`%c${message}`.trim(), data ?? "");
} }
// Log message received from the websocket to the console // Log message received from the websocket to the console
public static wsReceived(data: object, message: string | undefined = undefined): void { public wsReceived(data: object, message: string | undefined = undefined): void {
if (!this.enabled) return;
console.log(`%c[WS Recieved] ${message ?? ""}`.trim(), "color: #8258c7", data); console.log(`%c[WS Recieved] ${message ?? ""}`.trim(), "color: #8258c7", data);
} }
// Log message sent to the websocket to the console // Log message sent to the websocket to the console
public static wsSent(data: object, message: string | undefined = undefined): void { public wsSent(data: object, message: string | undefined = undefined): void {
if (!this.enabled) return;
console.log(`%c[WS Sent] ${message ?? ""}`.trim(), "color: #4eb570", data); console.log(`%c[WS Sent] ${message ?? ""}`.trim(), "color: #4eb570", data);
} }
// Log message to the console with a timestamp // Log message to the console with a timestamp
public static ts(message: string, data: object | null = null): void { public ts(message: string, data: object | null = null): void {
if (!this.enabled) return;
console.log(`%c[TS] ${message}`.trim(), "color: #2e6bc7", data ?? ""); console.log(`%c[TS] ${message}`.trim(), "color: #2e6bc7", data ?? "");
} }
} }