From 1315c39ae12d286743dd5156ccc8dcfafe9b81c4 Mon Sep 17 00:00:00 2001 From: Janis Date: Tue, 25 Oct 2022 18:27:02 +0200 Subject: [PATCH] first commit --- config.json | 1 + css/style.css | 25 ++++++++++++ img/muted_input.svg | 1 + img/muted_output.svg | 1 + img/off.svg | 1 + img/on.svg | 1 + js/app.js | 57 ++++++++++++++++++++++++++ js/display_content.js | 20 +++++++++ js/event_handlers.js | 94 +++++++++++++++++++++++++++++++++++++++++++ js/objects.js | 25 ++++++++++++ js/parser.js | 34 ++++++++++++++++ js/utils.js | 11 +++++ overlay.html | 26 ++++++++++++ 13 files changed, 297 insertions(+) create mode 100644 config.json create mode 100644 css/style.css create mode 100644 img/muted_input.svg create mode 100644 img/muted_output.svg create mode 100644 img/off.svg create mode 100644 img/on.svg create mode 100644 js/app.js create mode 100644 js/display_content.js create mode 100644 js/event_handlers.js create mode 100644 js/objects.js create mode 100644 js/parser.js create mode 100644 js/utils.js create mode 100644 overlay.html diff --git a/config.json b/config.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/config.json @@ -0,0 +1 @@ +{} diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..5569acd --- /dev/null +++ b/css/style.css @@ -0,0 +1,25 @@ +* { + font-family: Arial, Helvetica, sans-serif; + font-weight: bold; + color: white; + font-size: 70pt; + padding: 0; + margin: 0; + -webkit-text-stroke: 3px black; + background-color: black; +} +#content div { + margin-top: 5px; +} +.content-img { + float: left; + width: 100px; +} + +.content-img img { + display: block; +} + +.content-text { + margin-left: 130px; +} diff --git a/img/muted_input.svg b/img/muted_input.svg new file mode 100644 index 0000000..31da5ba --- /dev/null +++ b/img/muted_input.svg @@ -0,0 +1 @@ +muted_input \ No newline at end of file diff --git a/img/muted_output.svg b/img/muted_output.svg new file mode 100644 index 0000000..68c133e --- /dev/null +++ b/img/muted_output.svg @@ -0,0 +1 @@ +muted_output \ No newline at end of file diff --git a/img/off.svg b/img/off.svg new file mode 100644 index 0000000..e96add0 --- /dev/null +++ b/img/off.svg @@ -0,0 +1 @@ +player_off_v2 \ No newline at end of file diff --git a/img/on.svg b/img/on.svg new file mode 100644 index 0000000..2558730 --- /dev/null +++ b/img/on.svg @@ -0,0 +1 @@ +player_on_v2 \ No newline at end of file diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..2fc7cc5 --- /dev/null +++ b/js/app.js @@ -0,0 +1,57 @@ +function connectToTeamSpeak() { + const ws = new WebSocket("ws://localhost:5899"); + const paylaod = { + type: "auth", + payload: { + identifier: "de.tealfire.obs", + version: "0.0.1", + name: "TS5 OBS Overlay", + description: "A simple OBS overlay for TS5 by DerTyp876", + content: { + apiKey: "b02b521c-68bb-4971-a8d2-3f9f94b44d73", + }, + }, + }; + + ws.onopen = (event) => { + ws.send("Connected to TeamSpeak5"); + ws.send(JSON.stringify(paylaod)); + }; + + ws.onmessage = (event) => { + let data = JSON.parse(event.data); + //console.log(data); + + switch (data.type) { + case "auth": + handleAuthMessage(data); + break; + case "clientMoved": + handleClientMoved(data); + break; + case "clientPropertiesUpdated": + handleClientPropertiesUpdate(data); + break; + case "talkStatusChanged": + handleTalkStatusChanged(data); + break; + default: + console.log(`No handler for event type: ${data.type}`); + break; + } + drawClients(); + console.log(clients); + //console.log(channels); + }; + + ws.onerror = (err) => { + console.error(err); + connectToTeamSpeak(); + }; + + ws.onclose = (event) => { + console.log("Disconnected: " + event.reason); + connectToTeamSpeak(); + }; +} +connectToTeamSpeak(); diff --git a/js/display_content.js b/js/display_content.js new file mode 100644 index 0000000..f5007db --- /dev/null +++ b/js/display_content.js @@ -0,0 +1,20 @@ +function drawClients() { + let elem = document.getElementById("content"); + + result = ""; + getClientsInChannel(thisClient.channel).forEach((c) => { + result += '
'; + if (c.outputMuted) { + result += ' '; + } else if (c.inputMuted) { + result += ' '; + } else if (c.talkStatus == 1) { + result += ' '; + } else { + result += ' '; + } + result += "
"; + result += '
' + c.name + "
"; + }); + elem.innerHTML = result; +} diff --git a/js/event_handlers.js b/js/event_handlers.js new file mode 100644 index 0000000..de4a011 --- /dev/null +++ b/js/event_handlers.js @@ -0,0 +1,94 @@ +function handleAuthMessage(data) { + console.log("Handling auth message"); + channels = parseChannelInfos(data.payload.connections[0].channelInfos); + clients = parseClientInfos(data.payload.connections[0].clientInfos); + thisClient = clients.filter((obj) => { + return obj.id === data.payload.connections[0].clientId; + })[0]; +} + +function handleClientMoved(data) { + const client = clients.filter((obj) => { + return obj.id === data.payload.clientId; + })[0]; + + if (data.payload.newChannelId == 0) { + // User disconnected + if (client) { + console.log(`${client.name} disconnected`); + clients.splice(clients.indexOf(client), 1); + } + if (data.payload.clientId == thisClient.id) { + console.log("You disconnected"); + clients = []; + //! Maybe handle channel list here too + } + } else { + // User moved channel + if (client) { + // Client already exists in list + clients.filter((obj) => { + return obj.id === data.payload.clientId; + })[0].channel = channels.filter((obj) => { + return obj.id === data.payload.newChannelId; + })[0]; + } else { + // New Client has to be created + clients.push( + new Client( + data.payload.clientId, + channels.filter((obj) => { + return obj.id === data.payload.newChannelId; + })[0], + data.payload.properties.nickname + ) + ); + } + } +} + +function handleClientPropertiesUpdate(data) { + let client = clients.filter((obj) => { + return obj.id === data.payload.clientId; + })[0]; + if (data.payload.properties.channelGroupInheritedChannelId == 0) { + if (client) { + clients.splice(clients.indexOf(client), 1); + } + } else { + if (client) { + client.channel = channels.filter((obj) => { + return ( + obj.id === data.payload.properties.channelGroupInheritedChannelId + ); + })[0]; + + client.name = data.payload.properties.nickname; + client.inputMuted = data.payload.properties.inputMuted; + client.outputMuted = data.payload.properties.outputMuted; + } else { + clients.push( + new Client( + data.payload.clientId, + channels.filter((obj) => { + return ( + obj.id === data.payload.properties.channelGroupInheritedChannelId + ); + })[0], + data.payload.properties.nickname, + data.payload.properies.inputMuted, + data.payload.properies.outputMuted + ) + ); + } + } +} + +function handleTalkStatusChanged(data) { + let client = clients.filter((obj) => { + return obj.id === data.payload.clientId; + })[0]; + if (client) { + client.talkStatus = data.payload.status; + } +} diff --git a/js/objects.js b/js/objects.js new file mode 100644 index 0000000..3b861fd --- /dev/null +++ b/js/objects.js @@ -0,0 +1,25 @@ +class Channel { + constructor(id, name) { + this.id = id; + this.name = name; + } +} + +class Client { + constructor( + id, + channel, + name, + inputMuted = false, + outputMuted = false, + talkStatus = 0 + ) { + this.id = id; + this.channel = channel; + this.name = name; + this.inputMuted = inputMuted; + this.outputMuted = outputMuted; + this.talkStatus = talkStatus; + console.log(`Client created: ${this.id} - ${this.name}`); + } +} diff --git a/js/parser.js b/js/parser.js new file mode 100644 index 0000000..8f5456e --- /dev/null +++ b/js/parser.js @@ -0,0 +1,34 @@ +function parseChannelInfos(channelInfos) { + let result = []; + let rootChannels = channelInfos.rootChannels; + let subChannels = channelInfos.subChannels; + + rootChannels.forEach((rc) => { + result.push(new Channel(rc.id, rc.properties.name)); + + if (rc.id in subChannels) { + subChannels[rc.id].forEach((sc) => { + result.push(new Channel(sc.id, sc.properties.name)); + }); + } + }); + return result; +} + +function parseClientInfos(clientInfos) { + let result = []; + clientInfos.forEach((e) => { + result.push( + new Client( + e.id, + channels.filter((obj) => { + return obj.id === e.channelId; + })[0], + e.properties.nickname, + e.properties.inputMuted, + e.properties.outputMuted + ) + ); + }); + return result; +} diff --git a/js/utils.js b/js/utils.js new file mode 100644 index 0000000..0bfb7de --- /dev/null +++ b/js/utils.js @@ -0,0 +1,11 @@ +function getClientsInChannel(channel) { + let result = []; + + clients.forEach((e) => { + if (e.channel.id == channel.id) { + result.push(e); + } + }); + console.log(result); + return result; +} diff --git a/overlay.html b/overlay.html new file mode 100644 index 0000000..f6244c5 --- /dev/null +++ b/overlay.html @@ -0,0 +1,26 @@ + + + + + + + + TS5 - OBS Overlay + + + +
+ + + + + + + + + +