104 lines
2.4 KiB
TypeScript
104 lines
2.4 KiB
TypeScript
import {
|
|
genVoiceToken,
|
|
Payload,
|
|
WebSocket,
|
|
generateStreamKey,
|
|
} from "@spacebar/gateway";
|
|
import {
|
|
Channel,
|
|
Config,
|
|
emitEvent,
|
|
Region,
|
|
Snowflake,
|
|
Stream,
|
|
StreamSession,
|
|
} from "@spacebar/util";
|
|
|
|
interface StreamCreateSchema {
|
|
type: "guild" | "call";
|
|
channel_id: string;
|
|
guild_id?: string;
|
|
preferred_region?: string;
|
|
}
|
|
|
|
export async function onStreamCreate(this: WebSocket, data: Payload) {
|
|
const body = data.d as StreamCreateSchema;
|
|
|
|
// TODO: first check if we are in a voice channel already. cannot create a stream if there's no existing voice connection
|
|
if (body.channel_id.trim().length === 0) return;
|
|
|
|
// TODO: permissions check - if it's a guild, check if user is allowed to create stream in this guild
|
|
|
|
const channel = await Channel.findOne({
|
|
where: { id: body.channel_id },
|
|
});
|
|
|
|
if (
|
|
!channel ||
|
|
(body.type === "guild" && channel.guild_id != body.guild_id)
|
|
)
|
|
return this.close(4000, "invalid channel");
|
|
|
|
// TODO: actually apply preferred_region from the event payload
|
|
const regions = Config.get().regions;
|
|
const guildRegion = regions.available.filter(
|
|
(r) => r.id === regions.default,
|
|
)[0];
|
|
|
|
// create a new entry in db containing the token for authenticating user in stream gateway IDENTIFY
|
|
const stream = Stream.create({
|
|
id: Snowflake.generate(),
|
|
owner_id: this.user_id,
|
|
channel_id: body.channel_id,
|
|
endpoint: guildRegion.endpoint,
|
|
});
|
|
|
|
await stream.save();
|
|
|
|
const token = genVoiceToken();
|
|
|
|
const streamSession = StreamSession.create({
|
|
stream_id: stream.id,
|
|
user_id: this.user_id,
|
|
session_id: this.session_id,
|
|
token,
|
|
});
|
|
|
|
await streamSession.save();
|
|
|
|
const streamKey = generateStreamKey(
|
|
body.type,
|
|
body.guild_id,
|
|
body.channel_id,
|
|
this.user_id,
|
|
);
|
|
|
|
await emitEvent({
|
|
event: "STREAM_CREATE",
|
|
data: {
|
|
stream_key: streamKey,
|
|
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: [],
|
|
region: guildRegion.name,
|
|
paused: false,
|
|
},
|
|
guild_id: body.guild_id,
|
|
channel_id: body.channel_id,
|
|
});
|
|
|
|
await emitEvent({
|
|
event: "STREAM_SERVER_UPDATE",
|
|
data: {
|
|
token: streamSession.token,
|
|
stream_key: streamKey,
|
|
guild_id: null, // not sure why its always null
|
|
endpoint: stream.endpoint,
|
|
},
|
|
user_id: this.user_id,
|
|
});
|
|
}
|
|
|
|
//stream key:
|
|
// guild:${guild_id}:${channel_id}:${user_id}
|
|
// call:${channel_id}:${user_id}
|