summary refs log tree commit diff
path: root/api/src/util/VoiceState.ts
diff options
context:
space:
mode:
Diffstat (limited to 'api/src/util/VoiceState.ts')
-rw-r--r--api/src/util/VoiceState.ts54
1 files changed, 54 insertions, 0 deletions
diff --git a/api/src/util/VoiceState.ts b/api/src/util/VoiceState.ts
new file mode 100644

index 00000000..07022ec9 --- /dev/null +++ b/api/src/util/VoiceState.ts
@@ -0,0 +1,54 @@ +import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent } from "@fosscord/util"; +import { VoiceStateUpdateSchema } from "../schema"; + + +//TODO need more testing when community guild and voice stage channel are working +export async function updateVoiceState(vsuSchema: VoiceStateUpdateSchema, guildId: string, userId: string, targetUserId?: string) { + const perms = await getPermission(userId, guildId, vsuSchema.channel_id); + + /* + From https://discord.com/developers/docs/resources/guild#modify-current-user-voice-state + You must have the MUTE_MEMBERS permission to unsuppress yourself. You can always suppress yourself. + You must have the REQUEST_TO_SPEAK permission to request to speak. You can always clear your own request to speak. + */ + if (targetUserId !== undefined || (vsuSchema.suppress !== undefined && !vsuSchema.suppress)) { + perms.hasThrow("MUTE_MEMBERS"); + } + if (vsuSchema.request_to_speak_timestamp !== undefined && vsuSchema.request_to_speak_timestamp !== "") { + perms.hasThrow("REQUEST_TO_SPEAK") + } + + if (!targetUserId) { + targetUserId = userId; + } else { + if (vsuSchema.suppress !== undefined && vsuSchema.suppress) + vsuSchema.request_to_speak_timestamp = "" //Need to check if empty string is the right value + } + + //TODO assumed that empty string means clean, need to test if it's right + let voiceState + try { + voiceState = await VoiceState.findOneOrFail({ + guild_id: guildId, + channel_id: vsuSchema.channel_id, + user_id: targetUserId + }); + } catch (error) { + throw DiscordApiErrors.UNKNOWN_VOICE_STATE; + } + + voiceState.assign(vsuSchema); + const channel = await Channel.findOneOrFail({ guild_id: guildId, id: vsuSchema.channel_id }) + if (channel.type !== ChannelType.GUILD_STAGE_VOICE) { + throw DiscordApiErrors.CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE; + } + + await Promise.all([ + voiceState.save(), + emitEvent({ + event: "VOICE_STATE_UPDATE", + data: voiceState, + guild_id: guildId + } as VoiceStateUpdateEvent)]); + return; +} \ No newline at end of file