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; }
public RestClient(string botToken) { this.botToken = botToken; log = new DiscoreLogger("RestClient"); if (DiscordHttpClient.UseSingleHttpClient) { globalHttpClient = CreateHttpClient(); } }
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(); }
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); }
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); }
/// <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."); } } }
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(); }