From 5bae44faf0b325ff8f4f5fd703899b4706e858e7 Mon Sep 17 00:00:00 2001 From: dank074 Date: Wed, 16 Apr 2025 22:59:48 -0500 Subject: [PATCH] changes --- src/bundle/Server.ts | 7 +- src/gateway/opcodes/StreamWatch.ts | 116 ++++++++++++++++------------- src/webrtc/Server.ts | 8 +- src/webrtc/util/MediaServer.ts | 7 +- 4 files changed, 82 insertions(+), 56 deletions(-) diff --git a/src/bundle/Server.ts b/src/bundle/Server.ts index b34322a3..c3cfa04a 100644 --- a/src/bundle/Server.ts +++ b/src/bundle/Server.ts @@ -31,13 +31,18 @@ import { Config, initDatabase, Sentry } from "@spacebar/util"; const app = express(); const server = http.createServer(); const port = Number(process.env.PORT) || 3001; +const wrtcWsPort = Number(process.env.WRTC_WS_PORT) || 3004; const production = process.env.NODE_ENV == "development" ? false : true; server.on("request", app); const api = new Api.SpacebarServer({ server, port, production, app }); const cdn = new CDNServer({ server, port, production, app }); const gateway = new Gateway.Server({ server, port, production }); -const webrtc = new Webrtc.Server({ server: undefined, port: 3004, production }); +const webrtc = new Webrtc.Server({ + server: undefined, + port: wrtcWsPort, + production, +}); process.on("SIGTERM", async () => { console.log("Shutting down due to SIGTERM"); diff --git a/src/gateway/opcodes/StreamWatch.ts b/src/gateway/opcodes/StreamWatch.ts index f94a2f07..341076ae 100644 --- a/src/gateway/opcodes/StreamWatch.ts +++ b/src/gateway/opcodes/StreamWatch.ts @@ -14,59 +14,73 @@ export async function onStreamWatch(this: WebSocket, data: Payload) { const body = data.d as StreamWatchSchema; // TODO: apply perms: check if user is allowed to watch + + let parsedKey: { + type: "guild" | "call"; + channelId: string; + guildId?: string; + userId: string; + }; + try { - const { type, channelId, guildId, userId } = parseStreamKey( - body.stream_key, - ); - - const stream = await Stream.findOneOrFail({ - where: { channel_id: channelId, owner_id: userId }, - }); - - const streamSession = StreamSession.create({ - stream_id: stream.id, - user_id: this.user_id, - session_id: this.session_id, - token: genVoiceToken(), - }); - - await streamSession.save(); - - const regions = Config.get().regions; - const guildRegion = regions.available.find( - (r) => r.endpoint === stream.endpoint, - ); - - if (!guildRegion) return this.close(4000, "Unknown region"); - - const viewers = await StreamSession.find({ - where: { stream_id: stream.id }, - }); - - await emitEvent({ - event: "STREAM_CREATE", - data: { - stream_key: body.stream_key, - rtc_server_id: stream.id, // for voice connections in guilds it is guild_id, for dm voice calls it seems to be DM channel id, for GoLive streams a generated number - viewer_ids: viewers.map((v) => v.user_id), - region: guildRegion.name, - paused: false, - }, - guild_id: guildId, - channel_id: channelId, - }); - - await emitEvent({ - event: "STREAM_SERVER_UPDATE", - data: { - token: streamSession.token, - stream_key: body.stream_key, - guild_id: null, // not sure why its always null - endpoint: stream.endpoint, - }, - user_id: this.user_id, - }); + parsedKey = parseStreamKey(body.stream_key); } catch (e) { return this.close(4000, "Invalid stream key"); } + + const { type, channelId, guildId, userId } = parsedKey; + + const stream = await Stream.findOne({ + where: { channel_id: channelId, owner_id: userId }, + relations: ["channel"], + }); + + if (!stream) return this.close(4000, "Invalid stream key"); + + if (type === "guild" && stream.channel.guild_id != guildId) + return this.close(4000, "Invalid stream key"); + + const streamSession = StreamSession.create({ + stream_id: stream.id, + user_id: this.user_id, + session_id: this.session_id, + token: genVoiceToken(), + }); + + await streamSession.save(); + + const regions = Config.get().regions; + const guildRegion = regions.available.find( + (r) => r.endpoint === stream.endpoint, + ); + + if (!guildRegion) return this.close(4000, "Unknown region"); + + const viewers = await StreamSession.find({ + where: { stream_id: stream.id }, + }); + + await emitEvent({ + event: "STREAM_CREATE", + data: { + stream_key: body.stream_key, + rtc_server_id: stream.id, // for voice connections in guilds it is guild_id, for dm voice calls it seems to be DM channel id, for GoLive streams a generated number + viewer_ids: viewers.map((v) => v.user_id), + region: guildRegion.name, + paused: false, + }, + guild_id: guildId, + channel_id: channelId, + }); + + await emitEvent({ + event: "STREAM_SERVER_UPDATE", + data: { + token: streamSession.token, + stream_key: body.stream_key, + guild_id: null, // not sure why its always null + endpoint: stream.endpoint, + }, + user_id: this.user_id, + }); } diff --git a/src/webrtc/Server.ts b/src/webrtc/Server.ts index 40c39658..0bf67dad 100644 --- a/src/webrtc/Server.ts +++ b/src/webrtc/Server.ts @@ -22,6 +22,7 @@ import http from "http"; import ws from "ws"; import { Connection } from "./events/Connection"; import { + loadWebRtcLibrary, mediaServer, WRTC_PORT_MAX, WRTC_PORT_MIN, @@ -77,11 +78,14 @@ export class Server { await Config.init(); await initEvent(); - // if we failed to load webrtc library - if (!mediaServer) { + // try to load webrtc library, if failed just don't start webrtc endpoint + try { + await loadWebRtcLibrary(); + } catch (e) { console.log(`[WebRTC] ${yellow("WEBRTC disabled")}`); return Promise.resolve(); } + await mediaServer.start(WRTC_PUBLIC_IP, WRTC_PORT_MIN, WRTC_PORT_MAX); if (!this.server.listening) { this.server.listen(this.port); diff --git a/src/webrtc/util/MediaServer.ts b/src/webrtc/util/MediaServer.ts index 9842efb7..35abf3db 100644 --- a/src/webrtc/util/MediaServer.ts +++ b/src/webrtc/util/MediaServer.ts @@ -44,7 +44,7 @@ class NoConfiguredLibraryError implements Error { } } -(async () => { +export const loadWebRtcLibrary = async () => { try { //mediaServer = require('medooze-spacebar-wrtc'); if (!selectedWrtcLibrary) @@ -56,9 +56,12 @@ class NoConfiguredLibraryError implements Error { console.log( `[WebRTC] ${green(`Succesfully loaded ${selectedWrtcLibrary}`)}`, ); + return Promise.resolve(); } catch (error) { console.log( `[WebRTC] ${red(`Failed to import ${selectedWrtcLibrary}: ${error instanceof NoConfiguredLibraryError ? error.message : ""}`)}`, ); + + return Promise.reject(); } -})(); +};