-
-
Notifications
You must be signed in to change notification settings - Fork 318
build DiscordClient on top of IOC #1908
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
4d85806
4f42a50
eaf6a5e
1b0e386
6c22cd2
6fc8ed7
1e62cd4
5c8f2c4
b2ebdae
905ce60
68675df
32035b6
5a3e002
af572a6
06a7058
0fc1bbd
7284840
edd2984
ec97bdc
bfef5fc
8948ab0
a6de76c
72efde2
989eab0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| using System; | ||
|
|
||
| using DSharpPlus.Extensions; | ||
|
|
||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.Logging; | ||
|
|
||
| namespace DSharpPlus; | ||
|
|
||
| /// <summary> | ||
| /// Enables building a DiscordClient from complex configuration, registering extensions and fine-tuning behavioural aspects. | ||
| /// </summary> | ||
| public sealed class DiscordClientBuilder | ||
| { | ||
| private readonly IServiceCollection serviceCollection; | ||
| private bool addDefaultLogging = true; | ||
|
|
||
| /// <summary> | ||
| /// Creates a new DiscordClientBuilder from the provided service collection. This is private in favor of static | ||
| /// methods that control creation based on certain presets. IServiceCollection-based configuration occurs separate | ||
| /// from this type. | ||
| /// </summary> | ||
| private DiscordClientBuilder(IServiceCollection serviceCollection) | ||
| => this.serviceCollection = serviceCollection; | ||
|
|
||
| /// <summary> | ||
| /// Creates a new DiscordClientBuilder without sharding, using the specified token. | ||
| /// </summary> | ||
| /// <param name="token">The token to use for this application.</param> | ||
| /// <param name="serviceCollection">The service collection to base this builder on.</param> | ||
| /// <returns>A new DiscordClientBuilder.</returns> | ||
| public static DiscordClientBuilder Default(string token, IServiceCollection? serviceCollection = null) | ||
| { | ||
| serviceCollection ??= new ServiceCollection(); | ||
|
|
||
| DiscordClientBuilder builder = new(serviceCollection); | ||
| builder.serviceCollection.Configure<TokenContainer>(x => x.GetToken = () => token); | ||
| builder.serviceCollection.AddDSharpPlusDefaultsSingleShard(); | ||
|
|
||
| return builder; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Disables the DSharpPlus default logger for this DiscordClientBuilder. | ||
| /// </summary> | ||
| /// <returns>The current instance for chaining.</returns> | ||
| public DiscordClientBuilder DisableDefaultLogging() | ||
| { | ||
| this.addDefaultLogging = false; | ||
| return this; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Builds a new client from the present builder. | ||
| /// </summary> | ||
| public DiscordClient Build() | ||
| { | ||
| if (this.addDefaultLogging) | ||
| { | ||
| this.serviceCollection.AddLogging(builder => builder.AddProvider(new DefaultLoggerProvider())); | ||
| } | ||
|
|
||
| IServiceProvider provider = this.serviceCollection.BuildServiceProvider(); | ||
| return provider.GetRequiredService<DiscordClient>(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| using System.Net.Http; | ||
|
|
||
| using DSharpPlus.Net; | ||
|
|
||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.Logging; | ||
| using Microsoft.Extensions.Options; | ||
|
|
||
| namespace DSharpPlus.Extensions; | ||
|
|
||
| public static class ServiceCollectionExtensions | ||
| { | ||
| internal static IServiceCollection AddDSharpPlusDefaultsSingleShard(this IServiceCollection serviceCollection) | ||
| { | ||
| // peripheral setup | ||
| serviceCollection.AddSingleton<IMessageCacheProvider, MessageCache>(); | ||
|
|
||
| // rest setup | ||
| serviceCollection.AddKeyedSingleton<HttpClient>("DSharpPlus.Rest.HttpClient") | ||
| .AddSingleton<RestClient> | ||
| ( | ||
| serviceProvider => | ||
| { | ||
| HttpClient client = serviceProvider.GetRequiredKeyedService<HttpClient>("DSharpPlus.Rest.HttpClient"); | ||
| ILogger<RestClient> logger = serviceProvider.GetRequiredService<ILogger<RestClient>>(); | ||
| IOptions<RestClientOptions> options = serviceProvider.GetRequiredService<IOptions<RestClientOptions>>(); | ||
| IOptions<TokenContainer> token = serviceProvider.GetRequiredService<IOptions<TokenContainer>>(); | ||
|
|
||
| return new(logger, client, options, token); | ||
| } | ||
| ); | ||
|
|
||
| return serviceCollection; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,10 @@ | |
| using System.Threading.Tasks; | ||
| using DSharpPlus.Exceptions; | ||
| using DSharpPlus.Metrics; | ||
|
|
||
| using Microsoft.Extensions.Logging; | ||
| using Microsoft.Extensions.Options; | ||
|
|
||
| using Polly; | ||
|
|
||
| namespace DSharpPlus.Net; | ||
|
|
@@ -29,26 +32,34 @@ internal sealed partial class RestClient : IDisposable | |
|
|
||
| private volatile bool disposed; | ||
|
|
||
| internal RestClient(DiscordConfiguration config, ILogger logger) | ||
| internal RestClient | ||
| ( | ||
| ILogger<RestClient> logger, | ||
| HttpClient client, | ||
| IOptions<RestClientOptions> options, | ||
| IOptions<TokenContainer> tokenContainer | ||
| ) | ||
| : this | ||
| ( | ||
| config.Proxy, | ||
| config.HttpTimeout, | ||
| client, | ||
| options.Value.Timeout, | ||
| logger, | ||
| config.MaximumRatelimitRetries, | ||
| config.RatelimitRetryDelayFallback, | ||
| config.TimeoutForInitialApiRequest, | ||
| config.MaximumRestRequestsPerSecond | ||
| options.Value.MaximumRatelimitRetries, | ||
| options.Value.RatelimitRetryDelayFallback, | ||
| options.Value.InitialRequestTimeout, | ||
| options.Value.MaximumConcurrentRestRequests | ||
| ) | ||
| { | ||
| this.httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", Utilities.GetFormattedToken(config)); | ||
| string token = tokenContainer.Value.GetToken(); | ||
|
|
||
| this.httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", $"Bot {token}"); | ||
| this.httpClient.BaseAddress = new(Endpoints.BASE_URI); | ||
| } | ||
|
|
||
| // This is for meta-clients, such as the webhook client | ||
| internal RestClient | ||
| ( | ||
| IWebProxy proxy, | ||
| HttpClient client, | ||
| TimeSpan timeout, | ||
| ILogger logger, | ||
| int maxRetries = int.MaxValue, | ||
|
|
@@ -58,21 +69,10 @@ internal RestClient | |
| ) | ||
| { | ||
| this.logger = logger; | ||
| this.httpClient = client; | ||
|
|
||
| HttpClientHandler httphandler = new() | ||
| { | ||
| UseCookies = false, | ||
| AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip, | ||
| UseProxy = proxy != null, | ||
| Proxy = proxy | ||
| }; | ||
|
|
||
| this.httpClient = new HttpClient(httphandler) | ||
| { | ||
| BaseAddress = new Uri(Utilities.GetApiBaseUri()), | ||
| Timeout = timeout | ||
| }; | ||
|
|
||
| this.httpClient.BaseAddress = new Uri(Utilities.GetApiBaseUri()); | ||
| this.httpClient.Timeout = timeout; | ||
|
Comment on lines
+74
to
+75
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps it'd be worthwhile to go the Remora route and expose a [rest] client builder; there's occasional reason to change what the client does (e.g., adding additional polly handlers for metrics, or using the canary api for one reason or another)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Client builder as in
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think this is something we should look into in a separate pull request to customize specifically rest further |
||
| this.httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", Utilities.GetUserAgent()); | ||
| this.httpClient.BaseAddress = new(Endpoints.BASE_URI); | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.