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 60c69075..00820b06 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 @@ -93,7 +93,7 @@ router.patch( voice_state.save(), emitEvent({ event: "VOICE_STATE_UPDATE", - data: voice_state, + data: voice_state.toPublicVoiceState(), guild_id, } as VoiceStateUpdateEvent), ]); diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts index f46e69c2..fbf579ff 100644 --- a/src/gateway/opcodes/Identify.ts +++ b/src/gateway/opcodes/Identify.ts @@ -490,7 +490,9 @@ export async function onIdentify(this: WebSocket, data: Payload) { guilds.filter((guild) => !guild.unavailable) as Guild[] ).map((guild) => { return { - voice_states: guild.voice_states, + voice_states: guild.voice_states.map((state) => + state.toPublicVoiceState(), + ), id: guild.id, embedded_activities: [], }; diff --git a/src/gateway/opcodes/StreamCreate.ts b/src/gateway/opcodes/StreamCreate.ts index fdccd70c..80325a2f 100644 --- a/src/gateway/opcodes/StreamCreate.ts +++ b/src/gateway/opcodes/StreamCreate.ts @@ -120,7 +120,7 @@ export async function onStreamCreate(this: WebSocket, data: Payload) { await emitEvent({ event: "VOICE_STATE_UPDATE", - data: { ...voiceState }, + data: voiceState.toPublicVoiceState(), guild_id: voiceState.guild_id, channel_id: voiceState.channel_id, } as VoiceStateUpdateEvent); diff --git a/src/gateway/opcodes/StreamDelete.ts b/src/gateway/opcodes/StreamDelete.ts index dae7de60..76c87029 100644 --- a/src/gateway/opcodes/StreamDelete.ts +++ b/src/gateway/opcodes/StreamDelete.ts @@ -59,7 +59,7 @@ export async function onStreamDelete(this: WebSocket, data: Payload) { await emitEvent({ event: "VOICE_STATE_UPDATE", - data: { ...voiceState }, + data: voiceState.toPublicVoiceState(), guild_id: guildId, channel_id: channelId, } as VoiceStateUpdateEvent); diff --git a/src/gateway/opcodes/VoiceStateUpdate.ts b/src/gateway/opcodes/VoiceStateUpdate.ts index 0e9267b5..61dad0cd 100644 --- a/src/gateway/opcodes/VoiceStateUpdate.ts +++ b/src/gateway/opcodes/VoiceStateUpdate.ts @@ -68,7 +68,7 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { ) { await emitEvent({ event: "VOICE_STATE_UPDATE", - data: { ...voiceState, channel_id: null }, + data: { ...voiceState.toPublicVoiceState(), channel_id: null }, guild_id: voiceState.guild_id, }); } @@ -96,7 +96,11 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { ) { await emitEvent({ event: "VOICE_STATE_UPDATE", - data: { ...voiceState, channel_id: null, guild_id: null }, + data: { + ...voiceState.toPublicVoiceState(), + channel_id: null, + guild_id: null, + }, guild_id: prevState?.guild_id, channel_id: prevState?.channel_id, }); @@ -117,13 +121,16 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { voiceState.token = genVoiceToken(); voiceState.session_id = this.session_id; - const { id, member, ...newObj } = voiceState; + const { member } = voiceState; await Promise.all([ voiceState.save(), emitEvent({ event: "VOICE_STATE_UPDATE", - data: { ...newObj, member: member?.toPublicMember() }, + data: { + ...voiceState.toPublicVoiceState(), + member: member?.toPublicMember(), + }, guild_id: voiceState.guild_id, channel_id: voiceState.channel_id, user_id: voiceState.user_id, diff --git a/src/util/entities/VoiceState.ts b/src/util/entities/VoiceState.ts index 83a0af63..549d667f 100644 --- a/src/util/entities/VoiceState.ts +++ b/src/util/entities/VoiceState.ts @@ -24,6 +24,29 @@ import { Member } from "./Member"; import { User } from "./User"; import { dbEngine } from "../util/Database"; +export enum PublicVoiceStateEnum { + user_id, + suppress, + session_id, + self_video, + self_mute, + self_deaf, + self_stream, + request_to_speak_timestamp, + mute, + deaf, + channel_id, + guild_id, +} + +export type PublicVoiceStateKeys = keyof typeof PublicVoiceStateEnum; + +export const PublicVoiceStateProjection = Object.values( + PublicVoiceStateEnum, +).filter((x) => typeof x === "string") as PublicVoiceStateKeys[]; + +export type PublicVoiceState = Pick; + //https://gist.github.com/vassjozsef/e482c65df6ee1facaace8b3c9ff66145#file-voice_state-ex @Entity({ name: "voice_states", @@ -96,4 +119,13 @@ export class VoiceState extends BaseClass { @Column({ nullable: true, default: null }) request_to_speak_timestamp?: Date; + + toPublicVoiceState() { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const voiceState: any = {}; + PublicVoiceStateProjection.forEach((x) => { + voiceState[x] = this[x]; + }); + return voiceState as PublicVoiceState; + } } diff --git a/src/util/interfaces/Event.ts b/src/util/interfaces/Event.ts index 848dcd2e..5ef3b05d 100644 --- a/src/util/interfaces/Event.ts +++ b/src/util/interfaces/Event.ts @@ -21,7 +21,6 @@ import { ConnectedAccount, Interaction, ApplicationCommand, - VoiceState, Message, PartialEmoji, Invite, @@ -43,6 +42,7 @@ import { ReadyPrivateChannel, GuildOrUnavailable, GuildCreateResponse, + PublicVoiceState, } from "@spacebar/util"; export interface Event { @@ -431,7 +431,7 @@ export interface UserConnectionsUpdateEvent extends Event { export interface VoiceStateUpdateEvent extends Event { event: "VOICE_STATE_UPDATE"; - data: VoiceState & { + data: PublicVoiceState & { member: PublicMember; }; }