Skip to content

Commit

Permalink
v3.0.0 (#10)
Browse files Browse the repository at this point in the history
* Fix a potential memory leak and remove reliability stuff

* Use IOptions package

* FIx up samples

* Update README.md

* Update README.md

* v3.0.0

* Cleanup

* Update copyright

* Update README.md
  • Loading branch information
Hawxy authored Jun 14, 2020
1 parent 7aee911 commit cc65ef9
Show file tree
Hide file tree
Showing 17 changed files with 183 additions and 371 deletions.
1 change: 1 addition & 0 deletions Discord.Addons.Hosting/CommandServiceInitializerHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
#endregion
using System.Threading;
using System.Threading.Tasks;
using Discord.Addons.Hosting.Util;
using Discord.Commands;
using Microsoft.Extensions.Logging;

Expand Down
10 changes: 5 additions & 5 deletions Discord.Addons.Hosting/Discord.Addons.Hosting.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<PackageId>Discord.Addons.Hosting</PackageId>
<Version>2.1.0</Version>
<Version>3.0.0</Version>
<Authors>Hawxy</Authors>
<Description>Simplifying Discord.Net hosting with .NET Generic Host (Microsoft.Extensions.Hosting)</Description>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
Expand All @@ -12,16 +12,16 @@
<RepositoryUrl>https://github.com/Hawxy/Discord.Addons.Hosting</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageIcon>icon.png</PackageIcon>
<Copyright>Hawxy 2018-2019</Copyright>
<Copyright>Hawxy 2018-2020</Copyright>
<PackageTags>discord,discord.net,addon,hosting,microsoft.extensions.hosting</PackageTags>
<Nullable>Enable</Nullable>
<LangVersion>8.0</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Discord.Net.Commands" Version="2.1.1" />
<PackageReference Include="Discord.Net.WebSocket" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0" />
<PackageReference Include="Discord.Net.Commands" Version="2.2.0" />
<PackageReference Include="Discord.Net.WebSocket" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.5" />
</ItemGroup>

<ItemGroup>
Expand Down
49 changes: 26 additions & 23 deletions Discord.Addons.Hosting/DiscordHostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ limitations under the License.
#endregion
using System;
using System.Linq;
using Discord.Addons.Hosting.Util;
using Discord.Commands;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;

namespace Discord.Addons.Hosting
{
Expand All @@ -30,37 +32,29 @@ namespace Discord.Addons.Hosting
public static class DiscordHostBuilderExtensions
{
/// <summary>
/// Adds and configures a Discord.Net hosted instance of type <typeparamref name="T"/>
/// Adds and optionally configures a Discord.Net hosted instance of type <typeparamref name="T"/>
/// </summary>
/// <remarks>
/// A <see cref="HostBuilderContext"/> is supplied so that the configuration and service provider can be used.
/// </remarks>
/// <typeparam name="T">The type of Discord.Net client. Type must be or inherit from <see cref="DiscordSocketClient"/></typeparam>
/// <param name="builder">The host builder to configure.</param>
/// <param name="config">The delegate for the <see cref="IDiscordHostConfigurationBuilder" /> that will be used to construct the discord client.</param>
/// <param name="config">The delegate for the <see cref="DiscordHostConfiguration" /> that will be used to configure the host.</param>
/// <returns>The generic host builder.</returns>
/// <exception cref="ArgumentNullException">Thrown if <see cref="config"/> is null</exception>
/// <exception cref="InvalidOperationException">Thrown if client is already added to the service collection</exception>
public static IHostBuilder ConfigureDiscordHost<T>(this IHostBuilder builder, Action<HostBuilderContext, IDiscordHostConfigurationBuilder> config) where T : DiscordSocketClient
public static IHostBuilder ConfigureDiscordHost<T>(this IHostBuilder builder, Action<HostBuilderContext, DiscordHostConfiguration>? config = null) where T : DiscordSocketClient
{
if (config == null)
throw new ArgumentNullException(nameof(config));

builder.ConfigureServices((context, collection) =>
{
if (collection.Any(x => x.ServiceType == typeof(DiscordSocketClient)))
throw new InvalidOperationException($"Cannot add more than one Discord Client to host");

var dschostbuilder = new DiscordHostConfigurationBuilder();
config(context, dschostbuilder);

var dsconfig = dschostbuilder.Build();
collection.AddOptions<DiscordHostConfiguration>().Validate(x => ValidateToken(x.Token));

collection.AddSingleton(dsconfig);
if (config != null)
collection.Configure<DiscordHostConfiguration>(x => config(context, x));

var discordClient = (T)Activator.CreateInstance(typeof(T), dsconfig.SocketConfig);

collection.AddSingleton(discordClient);
collection.AddSingleton(x=> (T)Activator.CreateInstance(typeof(T), x.GetService<IOptions<DiscordHostConfiguration>>().Value.SocketConfig));
if(typeof(T) != typeof(DiscordSocketClient))
collection.AddSingleton<DiscordSocketClient>(x => x.GetRequiredService<T>());

Expand All @@ -70,6 +64,19 @@ public static IHostBuilder ConfigureDiscordHost<T>(this IHostBuilder builder, Ac

return builder;

static bool ValidateToken(string token)
{
try
{
TokenUtils.ValidateToken(TokenType.Bot, token);
return true;
}
catch (Exception e) when (e is ArgumentNullException || e is ArgumentException)
{
return false;
}
}

}

/// <summary>
Expand All @@ -78,11 +85,7 @@ public static IHostBuilder ConfigureDiscordHost<T>(this IHostBuilder builder, Ac
/// <param name="builder">The host builder to configure.</param>
/// <returns>The (generic) host builder.</returns>
/// <exception cref="InvalidOperationException">Thrown if <see cref="CommandService"/> is already added to the collection</exception>
public static IHostBuilder UseCommandService(this IHostBuilder builder)
{
builder.UseCommandService((context, config) => { });
return builder;
}
public static IHostBuilder UseCommandService(this IHostBuilder builder) => builder.UseCommandService((context, config) => { });

/// <summary>
/// Adds a <see cref="CommandService"/> instance to the host for use with a Discord.Net client. />
Expand All @@ -105,9 +108,9 @@ public static IHostBuilder UseCommandService(this IHostBuilder builder, Action<H
if (collection.Any(x => x.ServiceType == typeof(CommandService)))
throw new InvalidOperationException("Cannot add more than one CommandService to host");

var csc = new CommandServiceConfig();
config(context, csc);
collection.AddSingleton(new CommandService(csc));
collection.Configure<CommandServiceConfig>(x => config(context, x));

collection.AddSingleton(x=> new CommandService(x.GetService<IOptions<CommandServiceConfig>>().Value));
collection.AddHostedService<CommandServiceInitializerHost>();
});

Expand Down
29 changes: 29 additions & 0 deletions Discord.Addons.Hosting/DiscordHostConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#region License
/*
Copyright 2019 Hawxy
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#endregion
using System;
using Discord.WebSocket;

namespace Discord.Addons.Hosting
{
public class DiscordHostConfiguration
{
public string Token { get; set; } = string.Empty;
public Func<LogMessage, Exception, string> LogFormat { get; set; } = (message, exception) => $"{message.Source}: {message.Message}";
public DiscordSocketConfig SocketConfig { get; set; } = new DiscordSocketConfig();
}
}
74 changes: 0 additions & 74 deletions Discord.Addons.Hosting/DiscordHostConfigurationBuilder.cs

This file was deleted.

32 changes: 23 additions & 9 deletions Discord.Addons.Hosting/DiscordHostedService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ limitations under the License.
*/
#endregion

using System;
using System.Threading;
using System.Threading.Tasks;
using Discord.Addons.Hosting.Util;
using Discord.WebSocket;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Discord.Addons.Hosting
{
Expand All @@ -30,29 +33,40 @@ internal class DiscordHostedService : IHostedService
private readonly DiscordSocketClient _client;
private readonly DiscordHostConfiguration _config;

public DiscordHostedService(ILogger<DiscordHostedService> logger, DiscordHostConfiguration config, LogAdapter<DiscordSocketClient> adapter, DiscordSocketClient client)
public DiscordHostedService(ILogger<DiscordHostedService> logger, IOptions<DiscordHostConfiguration> options, LogAdapter<DiscordSocketClient> adapter, DiscordSocketClient client)
{
_logger = logger;
_config = config;
_config = options.Value;
_client = client;
_client.Log += adapter.Log;
}

public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Discord.Net hosted service is starting");
await _client.LoginAsync(TokenType.Bot, _config.Token);
var task = _client.StartAsync();
await Task.WhenAny(task, Task.Delay(Timeout.Infinite, cancellationToken));
if(cancellationToken.IsCancellationRequested) _logger.LogWarning("Startup has been aborted, exiting...");

try
{
await _client.LoginAsync(TokenType.Bot, _config.Token).WithCancellation(cancellationToken);
await _client.StartAsync().WithCancellation(cancellationToken);
}
catch (OperationCanceledException)
{
_logger.LogWarning("Startup has been aborted, exiting...");
}
}

public async Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Discord.Net hosted service is stopping");
var task = _client.StopAsync();
await Task.WhenAny(task, Task.Delay(Timeout.Infinite, cancellationToken));
if (cancellationToken.IsCancellationRequested) _logger.LogCritical("Discord.NET client could not be stopped within the given timeout and may have permanently deadlocked");
try
{
await _client.StopAsync().WithCancellation(cancellationToken);
}
catch (OperationCanceledException)
{
_logger.LogCritical("Discord.NET client could not be stopped within the given timeout and may have permanently deadlocked");
}
}
}
}
79 changes: 0 additions & 79 deletions Discord.Addons.Hosting/Reliability/ReliableDiscordHost.cs

This file was deleted.

Loading

0 comments on commit cc65ef9

Please sign in to comment.