public static Task <DiscordVoiceSession> JoinVoiceChannelAsync(this DiscordSocketClient client, VoiceStateProperties properties) { if (!properties.ChannelProperty.Set || !properties.ChannelId.HasValue) { throw new ArgumentNullException("ChannelId can not be null"); } properties.Fill(client); ulong guildId = properties.GuildId ?? 0; if (client.VoiceSessions.TryGetValue(guildId, out var oldSession)) { oldSession.Disconnect(); } CancellationTokenSource source = new CancellationTokenSource(); TaskCompletionSource <DiscordVoiceSession> task = new TaskCompletionSource <DiscordVoiceSession>(); void serverHandler(DiscordMediaSession session, DiscordMediaServer server) { source.Cancel(); if (server.Endpoint != null) { session.OnServerUpdated -= serverHandler; if (task.Task.Status != TaskStatus.Faulted) { task.SetResult((DiscordVoiceSession)session); } } } void stateHandler(DiscordSocketClient c, DiscordVoiceState state) { if (state.Channel != null && state.Channel.Id == properties.ChannelId.Value) { client.OnSessionVoiceState -= stateHandler; DiscordVoiceSession session = client.VoiceSessions[guildId] = new DiscordVoiceSession(client, properties.GuildId, properties.ChannelId.Value, state.SessionId); session.OnDisconnected += (s, args) => client.VoiceSessions.Remove(guildId); session.OnServerUpdated += serverHandler; } } client.OnSessionVoiceState += stateHandler; client.ChangeVoiceState(properties); if (client.Config.VoiceChannelConnectTimeout > 0) { Task.Run(async() => { await Task.Delay(client.Config.VoiceChannelConnectTimeout, source.Token); if (!source.IsCancellationRequested) { task.SetException(new TimeoutException("Gateway did not respond with a server")); } }); } return(task.Task); }
/// <summary> /// Changes a client's voice state /// </summary> public static void ChangeVoiceState(this DiscordSocketClient client, VoiceStateProperties properties) { client.Send(GatewayOpcode.VoiceStateUpdate, properties.Fill(client)); }