Exemple #1
0
        public VoiceWebSocket(string loggingName)
            : base(loggingName)
        {
            log = new DiscoreLogger(loggingName);

            InitializePayloadHandlers();
        }
        protected DiscordClientWebSocket(string loggingName)
        {
            log = new DiscoreLogger($"DiscordClientWebSocket:{loggingName}");

            socket = new ClientWebSocket();
            // Disable "keep alive" packets, Discord's WebSocket servers do not handle
            // these and will disconnect us with an 'decode error'.
            socket.Options.KeepAliveInterval = TimeSpan.Zero;
        }
Exemple #3
0
        public RestClient(string botToken)
        {
            this.botToken = botToken;

            log = new DiscoreLogger("RestClient");

            if (DiscordHttpClient.UseSingleHttpClient)
            {
                globalHttpClient = CreateHttpClient();
            }
        }
Exemple #4
0
        public GatewaySocket(string loggingName, int sequence,
                             GatewayRateLimiter outboundPayloadRateLimiter, GatewayRateLimiter gameStatusUpdateRateLimiter,
                             GatewayRateLimiter identifyRateLimiter)
            : base(loggingName)
        {
            this.sequence = sequence;
            this.outboundPayloadRateLimiter  = outboundPayloadRateLimiter;
            this.gameStatusUpdateRateLimiter = gameStatusUpdateRateLimiter;
            this.identifyRateLimiter         = identifyRateLimiter;

            log = new DiscoreLogger(loggingName);

            InitializePayloadHandlers();
        }
Exemple #5
0
        public Shard(string botToken, int shardId, int totalShards)
        {
            Id = shardId;

            log = new DiscoreLogger($"Shard#{shardId}");

            stoppedResetEvent = new AsyncManualResetEvent(true);

            Cache = new DiscordShardCache();

            gateway                = new Gateway(botToken, this, totalShards);
            gateway.OnFailure     += Gateway_OnFailure;
            gateway.OnReconnected += Gateway_OnReconnected;

            Voice = new ShardVoiceManager(this, gateway);
        }
Exemple #6
0
        public VoiceUdpSocket(string loggingName, int ssrc)
        {
            log = new DiscoreLogger(loggingName);

            this.ssrc = ssrc;
            encoder   = new OpusEncoder(48000, 2, 20, null, OpusApplication.MusicOrMixed);

            // Create send buffer
            const int FRAME_LENGTH    = 20;
            const int BITS_PER_SAMPLE = 16;
            const int BUFFER_LENGTH   = 1000;

            int samplesPerFrame = encoder.InputSamplingRate / 1000 * FRAME_LENGTH;
            int sampleSize      = (BITS_PER_SAMPLE / 8) * encoder.InputChannels;
            int frameSize       = samplesPerFrame * sampleSize;

            sendBuffer = new CircularBuffer((int)Math.Ceiling(BUFFER_LENGTH / (double)FRAME_LENGTH) * frameSize);
        }
Exemple #7
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.");
                }
            }
        }
Exemple #8
0
        internal Gateway(string botToken, Shard shard, int totalShards)
        {
            this.botToken    = botToken;
            this.shard       = shard;
            this.totalShards = totalShards;

            http = new DiscordHttpClient(botToken);

            cache = shard.Cache;

            log   = new DiscoreLogger($"Gateway#{shard.Id}");
            state = GatewayState.Disconnected;

            handshakeCompleteEvent = new AsyncManualResetEvent();
            handshakeCompleteCancellationSource = new CancellationTokenSource();

            // Up-to-date rate limit parameters: https://discord.com/developers/docs/topics/gateway#rate-limiting
            identifyRateLimiter         = new GatewayRateLimiter(5, 1);    // 1 IDENTIFY per 5 seconds
            outboundPayloadRateLimiter  = new GatewayRateLimiter(60, 120); // 120 outbound payloads every 60 seconds
            gameStatusUpdateRateLimiter = new GatewayRateLimiter(60, 5);   // 5 status updates per minute

            InitializeDispatchHandlers();
        }