internal async Task OnVoiceStateUpdated(DiscordVoiceState voiceState)
        {
            if (isValid)
            {
                this.voiceState = voiceState;

                if (!isConnected && !isConnecting && token != null && endPoint != null)
                {
                    // Either the token or session ID can be received first,
                    // so we must check if we are ready to start in both cases.
                    await DoFullConnect();
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Initiates this voice connection.
        /// <para>
        /// Note: An <see cref="OperationCanceledException"/> will be thrown if the Gateway
        /// connection is closed while initiating.
        /// </para>
        /// </summary>
        /// <param name="startMute">Whether the current bot should connect self-muted.</param>
        /// <param name="startDeaf">Whether the current bot should connect self-deafened.</param>
        /// <exception cref="DiscordPermissionException">
        /// Thrown if the current bot does not have permission to connect to the voice channel.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown if connect is called more than once,
        /// if the voice channel is full and the current bot is not an admin,
        /// or if the shard behind this connection isn't running.
        /// </exception>
        /// <exception cref="OperationCanceledException">
        /// Thrown if the give cancellation token is cancelled or the Gateway connection is closed while initiating the voice connection.
        /// </exception>
        public async Task ConnectAsync(Snowflake voiceChannelId,
                                       bool startMute = false, bool startDeaf = false, CancellationToken?cancellationToken = null)
        {
            if (isValid)
            {
                if (!isConnecting && !IsConnected)
                {
                    // We need to guarantee that the shard user ID is available,
                    // so double-check that the shard is running.
                    if (!Shard.IsRunning)
                    {
                        throw new InvalidOperationException("Voice connection cannot be started while the parent shard is not running!");
                    }

                    // Ensure the API user has permission to connect (this is to avoid the 10s timeout (if possible) otherwise).
                    AssertUserCanJoin(guildId, voiceChannelId);

                    // Set state
                    voiceState = new DiscordVoiceState(guildId, Shard.UserId.Value, voiceChannelId);

                    // Create the logger
                    log = new DiscoreLogger($"VoiceConnection:{guildId}");

                    // Initiate the connection
                    isConnecting = true;
                    connectingCancellationSource = new CancellationTokenSource();

                    await gateway.SendVoiceStateUpdatePayload(guildId, voiceChannelId,
                                                              startMute, startDeaf, cancellationToken ?? CancellationToken.None).ConfigureAwait(false);

                    await ConnectionTimeout().ConfigureAwait(false);
                }
                else
                {
                    throw new InvalidOperationException("Voice connection is already connecting or is currently connected.");
                }
            }
        }