diff --git a/TODO b/TODO index 43a38094d..06301253f 100644 --- a/TODO +++ b/TODO @@ -9,10 +9,12 @@ - User - Voice - Webhook + - Ratelimiter with refit - Gateway - Models - Client - Socket + - use token * Receive * Compression - Voice (long) @@ -24,8 +26,11 @@ - Emoji - Guild - User + - Utilities + - Token Validation (port from @ChrisJ) - Tests - Unit test Gateway stability / deadlockability? + - Port ChrisJ's token validator tests - Extensions - Commands ? design - use finite's or quahu's diff --git a/src/Discord.Net/Discord.Net.csproj b/src/Discord.Net/Discord.Net.csproj index 806d2361b..cd23e7c45 100644 --- a/src/Discord.Net/Discord.Net.csproj +++ b/src/Discord.Net/Discord.Net.csproj @@ -7,4 +7,14 @@ Discord + + + + + + + + + + diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index 7fdd37045..130749d27 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -1,25 +1,20 @@ using Discord.Rest; using Discord.Socket; -using System; -using System.Collections.Generic; -using System.Text; namespace Discord { internal class DiscordClient : IDiscordClient { - public DiscordRestApi Rest => _restApi; - public DiscordGatewayApi Gateway => _gatewayApi; + public DiscordRestApi Rest { get; } + public DiscordGatewayApi Gateway { get; } private readonly DiscordConfig _config; - private readonly DiscordRestApi _restApi; - private readonly DiscordGatewayApi _gatewayApi; public DiscordClient(DiscordConfig config, DiscordRestApi restApi, DiscordGatewayApi gatewayApi) { _config = config; - _restApi = restApi; - _gatewayApi = gatewayApi; + Rest = restApi; + Gateway = gatewayApi; } } } diff --git a/src/Discord.Net/DiscordConfig.cs b/src/Discord.Net/DiscordConfig.cs index 2fb4de090..db3b45efd 100644 --- a/src/Discord.Net/DiscordConfig.cs +++ b/src/Discord.Net/DiscordConfig.cs @@ -27,7 +27,9 @@ namespace Discord /// The URI to use when connecting to the gateway. If specified, this will override the URI Discord instructs us to use. /// public Uri? GatewayUri = null; - + /// + /// SocketFactory gets or sets how a WebSocket will be created. + /// public SocketFactory SocketFactory { get; set; } = DefaultSocketFactory.Create; } } diff --git a/src/Discord.Net/IDiscordClient.cs b/src/Discord.Net/IDiscordClient.cs index 913726676..271db25d5 100644 --- a/src/Discord.Net/IDiscordClient.cs +++ b/src/Discord.Net/IDiscordClient.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; +using System.Net.Http.Headers; using Discord.Rest; using Discord.Socket; @@ -9,10 +6,15 @@ namespace Discord { internal interface IDiscordClient { - static IDiscordClient Create(DiscordConfig config) + static IDiscordClient Create(string token, DiscordConfig? config = default) { - var rest = new DiscordRestApi(config); - var gateway = new DiscordGatewayApi(config); + config = config ?? new DiscordConfig(); + + // todo: validate token + var tokenHeader = AuthenticationHeaderValue.Parse(token); + + var rest = new DiscordRestApi(config, tokenHeader); + var gateway = new DiscordGatewayApi(config, token); return new DiscordClient(config, rest, gateway); } diff --git a/src/Discord.Net/Rest/DiscordHttpClientHandler.cs b/src/Discord.Net/Rest/DiscordHttpClientHandler.cs new file mode 100644 index 000000000..cf3d75f1c --- /dev/null +++ b/src/Discord.Net/Rest/DiscordHttpClientHandler.cs @@ -0,0 +1,23 @@ +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; + +namespace Discord.Rest +{ + internal sealed class DiscordHttpClientHandler : HttpClientHandler + { + private readonly AuthenticationHeaderValue _token; + + public DiscordHttpClientHandler(AuthenticationHeaderValue token) + { + _token = token; + } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + request.Headers.Authorization = _token; + return base.SendAsync(request, cancellationToken); + } + } +} diff --git a/src/Discord.Net/Rest/DiscordRestApi.cs b/src/Discord.Net/Rest/DiscordRestApi.cs index 052d4adc4..24c682478 100644 --- a/src/Discord.Net/Rest/DiscordRestApi.cs +++ b/src/Discord.Net/Rest/DiscordRestApi.cs @@ -2,6 +2,7 @@ using System.Text.Json; using System.Threading.Tasks; using Refit; using Discord.Rest.Models; +using System.Net.Http.Headers; // This is essentially a reimplementation of Wumpus.Net.Rest namespace Discord.Rest @@ -10,7 +11,7 @@ namespace Discord.Rest { private readonly IDiscordRestApi _api; - public DiscordRestApi(DiscordConfig config) + public DiscordRestApi(DiscordConfig config, AuthenticationHeaderValue token) { var jsonOptions = new JsonSerializerOptions(); var refitSettings = new RefitSettings diff --git a/src/Discord.Net/Rest/JsonContentSerializer.cs b/src/Discord.Net/Rest/JsonContentSerializer.cs index dbbf0f0f4..9c03ad59e 100644 --- a/src/Discord.Net/Rest/JsonContentSerializer.cs +++ b/src/Discord.Net/Rest/JsonContentSerializer.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Text.Json; -using System.Text.Json.Serialization; using System.Threading.Tasks; using Refit; diff --git a/src/Discord.Net/Socket/DiscordGatewayApi.cs b/src/Discord.Net/Socket/DiscordGatewayApi.cs index ad2305d29..5f4744b90 100644 --- a/src/Discord.Net/Socket/DiscordGatewayApi.cs +++ b/src/Discord.Net/Socket/DiscordGatewayApi.cs @@ -6,18 +6,23 @@ namespace Discord.Socket { public class DiscordGatewayApi { - static readonly Uri DefaultGatewayUri = new Uri("wss://gateway.discord.gg"); + private readonly DiscordConfig _config; + private readonly string _token; - ISocket Socket { get; set; } + public ISocket Socket { get; set; } - public DiscordGatewayApi(DiscordConfig config) + public DiscordGatewayApi(DiscordConfig config, string token) { + _config = config; + _token = token; + Socket = config.SocketFactory(OnAborted, OnPacket); } public async Task ConnectAsync(Uri? gatewayUri) { - await Socket.ConnectAsync(gatewayUri ?? DefaultGatewayUri, CancellationToken.None).ConfigureAwait(false); + var baseUri = _config.GatewayUri ?? (gatewayUri ?? DiscordConfig.DefaultGatewayUri); + await Socket.ConnectAsync(baseUri, CancellationToken.None).ConfigureAwait(false); } public void OnAborted(Exception error) diff --git a/src/Discord.Net/Socket/Providers/DefaultSocket.cs b/src/Discord.Net/Socket/Providers/DefaultSocket.cs index 66fab72ce..e071444b0 100644 --- a/src/Discord.Net/Socket/Providers/DefaultSocket.cs +++ b/src/Discord.Net/Socket/Providers/DefaultSocket.cs @@ -88,6 +88,8 @@ namespace Discord.Socket.Providers } State = SocketState.Open; + _receiveTask = ReceiveAsync(); + // TODO: this should not be expected to fail _stateLock.Release(); openLock.Dispose();