diff --git a/assets/openapi.json b/assets/openapi.json index 21ee3e108..91aa31620 100644 Binary files a/assets/openapi.json and b/assets/openapi.json differ diff --git a/assets/schemas.json b/assets/schemas.json index 1cfdd3534..3fca9371a 100644 Binary files a/assets/schemas.json and b/assets/schemas.json differ diff --git a/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts index a8df4a2e4..2ee777fb0 100644 --- a/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts +++ b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts @@ -47,7 +47,7 @@ router.patch( const { guild_id } = req.params as { [key: string]: string }; const user_id = req.params.user_id === "@me" ? req.user_id : (req.params.user_id as string); - const perms = await getPermission(req.user_id, guild_id, body.channel_id); + const perms = await getPermission(req.user_id, guild_id, body.channel_id!); /* From https://discord.com/developers/docs/resources/guild#modify-current-user-voice-state @@ -63,7 +63,7 @@ router.patch( const voiceState = await VoiceState.findOne({ where: { guild_id, - channel_id: body.channel_id, + channel_id: body.channel_id!, user_id, }, }); @@ -71,7 +71,7 @@ router.patch( voiceState.assign(body); const channel = await Channel.findOneOrFail({ - where: { guild_id, id: body.channel_id }, + where: { guild_id, id: body.channel_id! }, }); if (channel.type !== ChannelType.GUILD_STAGE_VOICE) { throw DiscordApiErrors.CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE; @@ -80,7 +80,7 @@ router.patch( voiceState.member = await Member.findOneOrFail({ where: { id: voiceState.user_id, - guild_id: voiceState.guild_id, + guild_id: voiceState.guild_id!, }, }); diff --git a/src/database/entities/VoiceState.ts b/src/database/entities/VoiceState.ts index 1da29dd3a..8bde7949d 100644 --- a/src/database/entities/VoiceState.ts +++ b/src/database/entities/VoiceState.ts @@ -31,7 +31,7 @@ import { PublicVoiceState, PublicVoiceStateProjection } from "@spacebar/schemas" export class VoiceState extends BaseClass { @Column({ nullable: true }) @RelationId((voice_state: VoiceState) => voice_state.guild) - guild_id: string; + guild_id: string | null; @JoinColumn({ name: "guild_id", foreignKeyConstraintName: "FK_voice_state_guild_id" }) @ManyToOne(() => Guild, (guild) => guild.voice_states, { @@ -41,7 +41,7 @@ export class VoiceState extends BaseClass { @Column({ nullable: true }) @RelationId((voice_state: VoiceState) => voice_state.channel) - channel_id: string; + channel_id: string | null; @JoinColumn({ name: "channel_id", foreignKeyConstraintName: "FK_voice_state_channel_id" }) @ManyToOne(() => Channel, { diff --git a/src/gateway/events/Close.ts b/src/gateway/events/Close.ts index 0cdd57416..68d3e58d3 100644 --- a/src/gateway/events/Close.ts +++ b/src/gateway/events/Close.ts @@ -76,9 +76,7 @@ export async function Close(this: WebSocket, code: number, reason: Buffer) { const prevGuildId = voiceState.guild_id; const prevChannelId = voiceState.channel_id; - // @ts-expect-error channel_id is nullable voiceState.channel_id = null; - // @ts-expect-error guild_id is nullable voiceState.guild_id = null; voiceState.self_stream = false; voiceState.self_video = false; @@ -87,7 +85,7 @@ export async function Close(this: WebSocket, code: number, reason: Buffer) { voiceState.member = await Member.findOneOrFail({ where: { id: voiceState.user_id, - guild_id: prevGuildId, + guild_id: prevGuildId!, }, }); // let the users in previous guild/channel know that user disconnected @@ -98,7 +96,7 @@ export async function Close(this: WebSocket, code: number, reason: Buffer) { guild_id: prevGuildId, // have to send the previous guild_id because that's what client expects for disconnect messages member: voiceState.member.toPublicMember(), }, - guild_id: prevGuildId, + guild_id: prevGuildId!, channel_id: prevChannelId, } satisfies VoiceStateUpdateEvent); } diff --git a/src/gateway/opcodes/StreamCreate.ts b/src/gateway/opcodes/StreamCreate.ts index 66d3e356d..e4b7bd9d5 100644 --- a/src/gateway/opcodes/StreamCreate.ts +++ b/src/gateway/opcodes/StreamCreate.ts @@ -52,7 +52,7 @@ export async function onStreamCreate(this: WebSocket, data: Payload) { if (body.guild_id) { voiceState.member = await Member.findOneOrFail({ - where: { id: voiceState.user_id, guild_id: voiceState.guild_id }, + where: { id: voiceState.user_id, guild_id: voiceState.guild_id! }, // TODO: dm calls? relations: { user: true, roles: true }, }); } @@ -133,7 +133,7 @@ export async function onStreamCreate(this: WebSocket, data: Payload) { ...voiceState.toPublicVoiceState(), member: voiceState.member.toPublicMember(), }, - guild_id: voiceState.guild_id, + guild_id: voiceState.guild_id!, // TODO: figure out how this works for DM calls channel_id: voiceState.channel_id, } satisfies VoiceStateUpdateEvent); diff --git a/src/gateway/opcodes/StreamDelete.ts b/src/gateway/opcodes/StreamDelete.ts index 012a3eb32..ce63eb5a2 100644 --- a/src/gateway/opcodes/StreamDelete.ts +++ b/src/gateway/opcodes/StreamDelete.ts @@ -89,7 +89,7 @@ export async function onStreamDelete(this: WebSocket, data: Payload) { voiceState.member = await Member.findOneOrFail({ where: { id: voiceState.user_id, - guild_id: voiceState.guild_id, + guild_id: voiceState.guild_id!, // TODO: DM calls? }, }); diff --git a/src/gateway/opcodes/VoiceStateUpdate.ts b/src/gateway/opcodes/VoiceStateUpdate.ts index a7d42cd11..842a4e6a5 100644 --- a/src/gateway/opcodes/VoiceStateUpdate.ts +++ b/src/gateway/opcodes/VoiceStateUpdate.ts @@ -46,8 +46,8 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { const body = data.d as VoiceStateUpdateSchema; // TODO: should this be null? - if (body.channel_id == "") body.channel_id = undefined; - if (body.guild_id == "") body.guild_id = undefined; + if (body.channel_id === "") body.channel_id = null; + if (body.guild_id === "") body.guild_id = null; const isNew = body.channel_id === null && body.guild_id === null; let isChanged = false; @@ -100,8 +100,8 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { channel_id: null, guild_id: null, }, - guild_id: prevState?.guild_id, - channel_id: prevState?.channel_id, + guild_id: prevState?.guild_id ?? undefined, // should this be null? + channel_id: prevState?.channel_id ?? undefined, // should this be null? }); } @@ -110,7 +110,7 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { //TODO this may fail if (body.guild_id) { const member = await Member.findOne({ - where: { id: voiceState.user_id, guild_id: voiceState.guild_id }, + where: { id: voiceState.user_id, guild_id: voiceState.guild_id! }, relations: { user: true, roles: true }, }); @@ -133,16 +133,17 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { ...voiceState.toPublicVoiceState(), member: member?.toPublicMember(), }, - guild_id: voiceState.guild_id, - channel_id: voiceState.channel_id, + guild_id: voiceState.guild_id || undefined, // TODO: should this be null? + channel_id: voiceState.channel_id || undefined, // TODO: should this be null? user_id: voiceState.user_id, } satisfies VoiceStateUpdateEvent), ]); //If it's null it means that we are leaving the channel and this event is not needed if ((isNew || isChanged) && voiceState.channel_id !== null) { + // TODO: DM calls? const guild = await Guild.findOne({ - where: { id: voiceState.guild_id }, + where: { id: voiceState.guild_id! }, }); const regions = Config.get().regions; let guildRegion: ConfigVoiceRegion | undefined; diff --git a/src/schemas/uncategorised/VoiceStateUpdateSchema.ts b/src/schemas/uncategorised/VoiceStateUpdateSchema.ts index 1d4cee82a..dbb874f92 100644 --- a/src/schemas/uncategorised/VoiceStateUpdateSchema.ts +++ b/src/schemas/uncategorised/VoiceStateUpdateSchema.ts @@ -18,8 +18,8 @@ //TODO need more testing when community guild and voice stage channel are working export interface VoiceStateUpdateSchema { - guild_id?: string; - channel_id?: string; + guild_id?: string | null; + channel_id?: string | null; self_mute: boolean; self_deaf: boolean; self_video?: boolean; diff --git a/src/webrtc/opcodes/Identify.ts b/src/webrtc/opcodes/Identify.ts index 7d776d9cf..b51efe729 100644 --- a/src/webrtc/opcodes/Identify.ts +++ b/src/webrtc/opcodes/Identify.ts @@ -80,7 +80,7 @@ export async function onIdentify(this: WebRtcWebSocket, data: VoicePayload) { const voiceRoomId = type === "stream" ? server_id : voiceState!.channel_id; try { - this.webRtcClient = await mediaServer.join(voiceRoomId, this.user_id, this, type!); + this.webRtcClient = await mediaServer.join(voiceRoomId!, this.user_id, this, type!); } catch (e) { return this.close(4013); }