mirror of
https://github.com/oliverbooth/X10D
synced 2024-11-09 23:25:43 +00:00
Add X10D.Hosting & X10D.DSharpPlus
This commit is contained in:
parent
7e2650bd41
commit
87042d89ba
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
@ -32,6 +32,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
|
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
|
||||||
|
dotnet pack X10D.DSharpPlus -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
|
||||||
|
dotnet pack X10D.Hosting -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
|
||||||
dotnet pack X10D.Unity -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
|
dotnet pack X10D.Unity -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
|
||||||
|
|
||||||
- name: Push NuGet Package to GitHub
|
- name: Push NuGet Package to GitHub
|
||||||
|
2
.github/workflows/prerelease.yml
vendored
2
.github/workflows/prerelease.yml
vendored
@ -32,6 +32,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
|
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
|
||||||
|
dotnet pack X10D.DSharpPlus -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
|
||||||
|
dotnet pack X10D.Hosting -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
|
||||||
dotnet pack X10D.Unity -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
|
dotnet pack X10D.Unity -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
|
||||||
|
|
||||||
- name: Push NuGet Package to GitHub
|
- name: Push NuGet Package to GitHub
|
||||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -32,6 +32,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
|
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
|
||||||
|
dotnet pack X10D.DSharpPlus -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
|
||||||
|
dotnet pack X10D.Hosting -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
|
||||||
dotnet pack X10D.Unity -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
|
dotnet pack X10D.Unity -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
|
||||||
|
|
||||||
- name: Push NuGet Package to GitHub
|
- name: Push NuGet Package to GitHub
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
## 3.2.0
|
## 3.2.0
|
||||||
### Added
|
### Added
|
||||||
|
- Added new library X10D.DSharpPlus
|
||||||
|
- Added new library X10D.Hosting
|
||||||
|
|
||||||
- X10D: Added `MathUtility.InverseLerp(float, float, float)` and `MathUtility.InverseLerp(double, double, double)`
|
- X10D: Added `MathUtility.InverseLerp(float, float, float)` and `MathUtility.InverseLerp(double, double, double)`
|
||||||
- X10D: Added `Circle`, `CircleF`, `Cuboid`, `Ellipse`, `EllipseF`, `Line3D`, `Line`, `LineF`, `Polygon`, `PolygonF`, `Polyhedron`, and `Sphere`, to complement System.Drawing structs such as `Point` and `Rectangle`
|
- X10D: Added `Circle`, `CircleF`, `Cuboid`, `Ellipse`, `EllipseF`, `Line3D`, `Line`, `LineF`, `Polygon`, `PolygonF`, `Polyhedron`, and `Sphere`, to complement System.Drawing structs such as `Point` and `Rectangle`
|
||||||
- X10D: Added `Color.Deconstruct()` - with optional alpha parameter
|
- X10D: Added `Color.Deconstruct()` - with optional alpha parameter
|
||||||
|
61
X10D.DSharpPlus/X10D.DSharpPlus.csproj
Normal file
61
X10D.DSharpPlus/X10D.DSharpPlus.csproj
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>net6.0;netstandard2.1</TargetFrameworks>
|
||||||
|
<LangVersion>10.0</LangVersion>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<ImplicitUsings>true</ImplicitUsings>
|
||||||
|
<Authors>Oliver Booth</Authors>
|
||||||
|
<NeutralLanguage>en</NeutralLanguage>
|
||||||
|
<RepositoryUrl>https://github.com/oliverbooth/X10D</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<Description>Extension methods on crack.</Description>
|
||||||
|
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
|
||||||
|
<PackageIcon>icon.png</PackageIcon>
|
||||||
|
<PackageIconUrl/>
|
||||||
|
<PackageTags>dotnet extension-methods</PackageTags>
|
||||||
|
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
|
||||||
|
<VersionPrefix>3.2.0</VersionPrefix>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' == ''">
|
||||||
|
<Version>$(VersionPrefix)-$(VersionSuffix)</Version>
|
||||||
|
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
|
||||||
|
<FileVersion>$(VersionPrefix).0</FileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' != ''">
|
||||||
|
<Version>$(VersionPrefix)-$(VersionSuffix).$(BuildNumber)</Version>
|
||||||
|
<AssemblyVersion>$(VersionPrefix).$(BuildNumber)</AssemblyVersion>
|
||||||
|
<FileVersion>$(VersionPrefix).$(BuildNumber)</FileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(VersionSuffix)' == ''">
|
||||||
|
<Version>$(VersionPrefix)</Version>
|
||||||
|
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
|
||||||
|
<FileVersion>$(VersionPrefix).0</FileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="DSharpPlus" Version="4.3.0-nightly-01155" PrivateAssets="All"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\icon.png">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath/>
|
||||||
|
</None>
|
||||||
|
<None Include="..\LICENSE.md">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath/>
|
||||||
|
</None>
|
||||||
|
<None Include="..\CHANGELOG.md">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath/>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
80
X10D.DSharpPlus/src/DiscordChannelExtensions.cs
Normal file
80
X10D.DSharpPlus/src/DiscordChannelExtensions.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
using DSharpPlus;
|
||||||
|
using DSharpPlus.Entities;
|
||||||
|
|
||||||
|
namespace X10D.DSharpPlus;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="DiscordChannel" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class DiscordChannelExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the category of this channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channel">The channel whose category to retrieve.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The category of <paramref name="channel" />, or <paramref name="channel" /> itself if it is already a category;
|
||||||
|
/// <see langword="null" /> if this channel is not defined in a category.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="channel" /> is <see langword="null" />.</exception>
|
||||||
|
public static DiscordChannel? GetCategory(this DiscordChannel channel)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(channel);
|
||||||
|
#else
|
||||||
|
if (channel is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(channel));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (channel.IsCategory)
|
||||||
|
{
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel.Parent is not { } parent)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalizes a <see cref="DiscordChannel" /> so that the internal client is assured to be a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="channel">The <see cref="DiscordChannel" /> to normalize.</param>
|
||||||
|
/// <param name="client">The target client.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="DiscordChannel" /> whose public values will match <paramref name="channel" />, but whose internal client
|
||||||
|
/// is <paramref name="client" />.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <para><paramref name="channel" /> is <see langword="null" /></para>
|
||||||
|
/// -or-
|
||||||
|
/// <para><paramref name="client" /> is <see langword="null" /></para>
|
||||||
|
/// </exception>
|
||||||
|
public static async Task<DiscordChannel> NormalizeClientAsync(this DiscordChannel channel, DiscordClient client)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(channel);
|
||||||
|
ArgumentNullException.ThrowIfNull(client);
|
||||||
|
#else
|
||||||
|
if (channel is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(client));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return await client.GetChannelAsync(channel.Id);
|
||||||
|
}
|
||||||
|
}
|
34
X10D.DSharpPlus/src/DiscordClientExtensions.cs
Normal file
34
X10D.DSharpPlus/src/DiscordClientExtensions.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using DSharpPlus;
|
||||||
|
|
||||||
|
namespace X10D.DSharpPlus;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="DiscordClient" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class DiscordClientExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Instructs the client to automatically join all existing threads, and any newly-created threads.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client">The <see cref="DiscordClient" /> whose events should be subscribed.</param>
|
||||||
|
/// <param name="rejoinIfRemoved">
|
||||||
|
/// <see langword="true" /> to automatically rejoin a thread if this client was removed; otherwise,
|
||||||
|
/// <see langword="false" />.
|
||||||
|
/// </param>
|
||||||
|
public static void AutoJoinThreads(this DiscordClient client, bool rejoinIfRemoved = true)
|
||||||
|
{
|
||||||
|
client.GuildAvailable += (_, args) => args.Guild.JoinAllThreadsAsync();
|
||||||
|
client.ThreadCreated += (_, args) => args.Thread.JoinThreadAsync();
|
||||||
|
|
||||||
|
if (rejoinIfRemoved)
|
||||||
|
{
|
||||||
|
client.ThreadMembersUpdated += (_, args) =>
|
||||||
|
{
|
||||||
|
if (args.RemovedMembers.Any(m => m.Id == client.CurrentUser.Id))
|
||||||
|
return args.Thread.JoinThreadAsync();
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
211
X10D.DSharpPlus/src/DiscordEmbedBuilderExtensions.cs
Normal file
211
X10D.DSharpPlus/src/DiscordEmbedBuilderExtensions.cs
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
using DSharpPlus.Entities;
|
||||||
|
|
||||||
|
namespace X10D.DSharpPlus;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="DiscordEmbedBuilder" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class DiscordEmbedBuilderExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Conditionally adds a field to the embed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
|
||||||
|
/// <param name="condition">The condition whose value is used to determine whether the field will be added.</param>
|
||||||
|
/// <param name="name">The name of the embed field.</param>
|
||||||
|
/// <param name="value">The value of the embed field.</param>
|
||||||
|
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
|
||||||
|
/// <typeparam name="T">The type of <paramref name="value" />.</typeparam>
|
||||||
|
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="builder" /> is <see langword="null" />.</exception>
|
||||||
|
public static DiscordEmbedBuilder AddFieldIf<T>(
|
||||||
|
this DiscordEmbedBuilder builder,
|
||||||
|
bool condition,
|
||||||
|
string name,
|
||||||
|
T? value,
|
||||||
|
bool inline = false)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(builder);
|
||||||
|
#else
|
||||||
|
if (builder is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (condition)
|
||||||
|
{
|
||||||
|
builder.AddField(name, value?.ToString(), inline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Conditionally adds a field to the embed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
|
||||||
|
/// <param name="predicate">The predicate whose return value is used to determine whether the field will be added.</param>
|
||||||
|
/// <param name="name">The name of the embed field.</param>
|
||||||
|
/// <param name="value">The value of the embed field.</param>
|
||||||
|
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
|
||||||
|
/// <typeparam name="T">The type of <paramref name="value" />.</typeparam>
|
||||||
|
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <para><paramref name="builder" /> is <see langword="null" />.</para>
|
||||||
|
/// -or-
|
||||||
|
/// <para><paramref name="predicate" /> is <see langword="null" />.</para>
|
||||||
|
/// </exception>
|
||||||
|
public static DiscordEmbedBuilder AddFieldIf<T>(
|
||||||
|
this DiscordEmbedBuilder builder,
|
||||||
|
Func<bool> predicate,
|
||||||
|
string name,
|
||||||
|
T? value,
|
||||||
|
bool inline = false)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(builder);
|
||||||
|
ArgumentNullException.ThrowIfNull(predicate);
|
||||||
|
#else
|
||||||
|
if (builder is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (predicate is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(predicate));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (predicate.Invoke())
|
||||||
|
{
|
||||||
|
builder.AddField(name, value?.ToString(), inline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Conditionally adds a field to the embed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
|
||||||
|
/// <param name="predicate">The predicate whose return value is used to determine whether the field will be added.</param>
|
||||||
|
/// <param name="name">The name of the embed field.</param>
|
||||||
|
/// <param name="valueFactory">The delegate whose return value will be used as the value of the embed field.</param>
|
||||||
|
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
|
||||||
|
/// <typeparam name="T">The return type of <paramref name="valueFactory" />.</typeparam>
|
||||||
|
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <para><paramref name="builder" /> is <see langword="null" />.</para>
|
||||||
|
/// -or-
|
||||||
|
/// <para><paramref name="predicate" /> is <see langword="null" />.</para>
|
||||||
|
/// -or-
|
||||||
|
/// <para><paramref name="valueFactory" /> is <see langword="null" />.</para>
|
||||||
|
/// </exception>
|
||||||
|
public static DiscordEmbedBuilder AddFieldIf<T>(
|
||||||
|
this DiscordEmbedBuilder builder,
|
||||||
|
Func<bool> predicate,
|
||||||
|
string name,
|
||||||
|
Func<T?> valueFactory,
|
||||||
|
bool inline = false)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(builder);
|
||||||
|
ArgumentNullException.ThrowIfNull(predicate);
|
||||||
|
ArgumentNullException.ThrowIfNull(valueFactory);
|
||||||
|
#else
|
||||||
|
if (builder is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (predicate is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(predicate));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valueFactory is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(valueFactory));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (predicate.Invoke())
|
||||||
|
{
|
||||||
|
builder.AddField(name, valueFactory.Invoke()?.ToString(), inline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Conditionally adds a field to the embed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
|
||||||
|
/// <param name="condition">The condition whose value is used to determine whether the field will be added.</param>
|
||||||
|
/// <param name="name">The name of the embed field.</param>
|
||||||
|
/// <param name="valueFactory">The delegate whose return value will be used as the value of the embed field.</param>
|
||||||
|
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
|
||||||
|
/// <typeparam name="T">The return type of <paramref name="valueFactory" />.</typeparam>
|
||||||
|
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <para><paramref name="builder" /> is <see langword="null" />.</para>
|
||||||
|
/// -or-
|
||||||
|
/// <para><paramref name="valueFactory" /> is <see langword="null" />.</para>
|
||||||
|
/// </exception>
|
||||||
|
public static DiscordEmbedBuilder AddFieldIf<T>(
|
||||||
|
this DiscordEmbedBuilder builder,
|
||||||
|
bool condition,
|
||||||
|
string name,
|
||||||
|
Func<T?> valueFactory,
|
||||||
|
bool inline = false)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(builder);
|
||||||
|
ArgumentNullException.ThrowIfNull(valueFactory);
|
||||||
|
#else
|
||||||
|
if (builder is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
if (valueFactory is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(valueFactory));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (condition)
|
||||||
|
{
|
||||||
|
builder.AddField(name, valueFactory.Invoke()?.ToString(), inline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the embed's author.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The embed builder to modify.</param>
|
||||||
|
/// <param name="user">The author.</param>
|
||||||
|
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />.</returns>
|
||||||
|
public static DiscordEmbedBuilder WithAuthor(this DiscordEmbedBuilder builder, DiscordUser user)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(builder);
|
||||||
|
ArgumentNullException.ThrowIfNull(user);
|
||||||
|
#else
|
||||||
|
if (builder is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
if (user is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(user));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return builder.WithAuthor(user.Username, user.AvatarUrl);
|
||||||
|
}
|
||||||
|
}
|
63
X10D.DSharpPlus/src/DiscordGuildExtensions.cs
Normal file
63
X10D.DSharpPlus/src/DiscordGuildExtensions.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using DSharpPlus;
|
||||||
|
using DSharpPlus.Entities;
|
||||||
|
|
||||||
|
namespace X10D.DSharpPlus;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="DiscordGuild" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class DiscordGuildExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Joins all active threads in the guild that this client has permission to view.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="guild">The guild whose active threads to join.</param>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="guild" /> is <see langword="null" />.</exception>
|
||||||
|
public static async Task JoinAllThreadsAsync(this DiscordGuild guild)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(guild);
|
||||||
|
#else
|
||||||
|
if (guild is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(guild));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
await Task.WhenAll(guild.Threads.Values.Select(t => t.JoinThreadAsync()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalizes a <see cref="DiscordGuild" /> so that the internal client is assured to be a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="guild">The <see cref="DiscordGuild" /> to normalize.</param>
|
||||||
|
/// <param name="client">The target client.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="DiscordGuild" /> whose public values will match <paramref name="guild" />, but whose internal client is
|
||||||
|
/// <paramref name="client" />.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <para><paramref name="guild" /> is <see langword="null" /></para>
|
||||||
|
/// -or-
|
||||||
|
/// <para><paramref name="client" /> is <see langword="null" /></para>
|
||||||
|
/// </exception>
|
||||||
|
public static async Task<DiscordGuild> NormalizeClientAsync(this DiscordGuild guild, DiscordClient client)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(guild);
|
||||||
|
ArgumentNullException.ThrowIfNull(client);
|
||||||
|
#else
|
||||||
|
if (guild is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(guild));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(client));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return await client.GetGuildAsync(guild.Id);
|
||||||
|
}
|
||||||
|
}
|
73
X10D.DSharpPlus/src/DiscordMemberExtensions.cs
Normal file
73
X10D.DSharpPlus/src/DiscordMemberExtensions.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using DSharpPlus;
|
||||||
|
using DSharpPlus.Entities;
|
||||||
|
|
||||||
|
namespace X10D.DSharpPlus;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="DiscordMember" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class DiscordMemberExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether this member has the specified role.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="member">The member whose roles to search.</param>
|
||||||
|
/// <param name="role">The role for which to check.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if <paramref name="member" /> has the role; otherwise, <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
public static bool HasRole(this DiscordMember member, DiscordRole role)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(member);
|
||||||
|
ArgumentNullException.ThrowIfNull(role);
|
||||||
|
#else
|
||||||
|
if (member is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(member));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(role));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return member.Roles.Contains(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalizes a <see cref="DiscordMember" /> so that the internal client is assured to be a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="member">The <see cref="DiscordMember" /> to normalize.</param>
|
||||||
|
/// <param name="client">The target client.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="DiscordMember" /> whose public values will match <paramref name="member" />, but whose internal client
|
||||||
|
/// is <paramref name="client" />.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <para><paramref name="member" /> is <see langword="null" /></para>
|
||||||
|
/// -or-
|
||||||
|
/// <para><paramref name="client" /> is <see langword="null" /></para>
|
||||||
|
/// </exception>
|
||||||
|
public static async Task<DiscordMember> NormalizeClientAsync(this DiscordMember member, DiscordClient client)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(member);
|
||||||
|
ArgumentNullException.ThrowIfNull(client);
|
||||||
|
#else
|
||||||
|
if (member is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(member));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(client));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DiscordGuild guild = await member.Guild.NormalizeClientAsync(client);
|
||||||
|
return await guild.GetMemberAsync(member.Id);
|
||||||
|
}
|
||||||
|
}
|
89
X10D.DSharpPlus/src/DiscordMessageExtensions.cs
Normal file
89
X10D.DSharpPlus/src/DiscordMessageExtensions.cs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
using DSharpPlus;
|
||||||
|
using DSharpPlus.Entities;
|
||||||
|
|
||||||
|
namespace X10D.DSharpPlus;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="DiscordMessage" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class DiscordMessageExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes this message after a specified delay.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message to delete.</param>
|
||||||
|
/// <param name="delay">The delay before deletion.</param>
|
||||||
|
/// <param name="reason">The reason for the deletion.</param>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="message" /> is <see langword="null" />.</exception>
|
||||||
|
public static async Task DeleteAfterAsync(this DiscordMessage message, TimeSpan delay, string? reason = null)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(message);
|
||||||
|
#else
|
||||||
|
if (message is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(message));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
await Task.Delay(delay);
|
||||||
|
await message.DeleteAsync(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the message as created by this task after a specified delay.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task">The task whose <see cref="DiscordMessage" /> result should be deleted.</param>
|
||||||
|
/// <param name="delay">The delay before deletion.</param>
|
||||||
|
/// <param name="reason">The reason for the deletion.</param>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="task" /> is <see langword="null" />.</exception>
|
||||||
|
public static async Task DeleteAfterAsync(this Task<DiscordMessage> task, TimeSpan delay, string? reason = null)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(task);
|
||||||
|
#else
|
||||||
|
if (task is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(task));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DiscordMessage message = await task;
|
||||||
|
await message.DeleteAfterAsync(delay, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalizes a <see cref="DiscordMessage" /> so that the internal client is assured to be a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The <see cref="DiscordMessage" /> to normalize.</param>
|
||||||
|
/// <param name="client">The target client.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="DiscordMessage" /> whose public values will match <paramref name="message" />, but whose internal client
|
||||||
|
/// is <paramref name="client" />.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <para><paramref name="message" /> is <see langword="null" /></para>
|
||||||
|
/// -or-
|
||||||
|
/// <para><paramref name="client" /> is <see langword="null" /></para>
|
||||||
|
/// </exception>
|
||||||
|
public static async Task<DiscordMessage> NormalizeClientAsync(this DiscordMessage message, DiscordClient client)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(message);
|
||||||
|
ArgumentNullException.ThrowIfNull(client);
|
||||||
|
#else
|
||||||
|
if (message is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(client));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DiscordChannel channel = await message.Channel.NormalizeClientAsync(client);
|
||||||
|
return await channel.GetMessageAsync(message.Id);
|
||||||
|
}
|
||||||
|
}
|
158
X10D.DSharpPlus/src/DiscordUserExtensions.cs
Normal file
158
X10D.DSharpPlus/src/DiscordUserExtensions.cs
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
using DSharpPlus;
|
||||||
|
using DSharpPlus.Entities;
|
||||||
|
using DSharpPlus.Exceptions;
|
||||||
|
|
||||||
|
namespace X10D.DSharpPlus;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="DiscordUser" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class DiscordUserExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the current <see cref="DiscordUser" /> as a member of the specified guild.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The user to transform.</param>
|
||||||
|
/// <param name="guild">The guild whose member list to search.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="DiscordMember" /> whose <see cref="DiscordMember.Guild" /> is equal to <paramref name="guild" />, or
|
||||||
|
/// <see langword="null" /> if this user is not in the specified <paramref name="guild" />.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <para><paramref name="user" /> is <see langword="null" />.</para>
|
||||||
|
/// -or-
|
||||||
|
/// <para><paramref name="guild" /> is <see langword="null" />.</para>
|
||||||
|
/// </exception>
|
||||||
|
public static async Task<DiscordMember?> GetAsMemberOfAsync(this DiscordUser user, DiscordGuild guild)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(user);
|
||||||
|
ArgumentNullException.ThrowIfNull(guild);
|
||||||
|
#else
|
||||||
|
if (user is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guild is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(guild));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (user is DiscordMember member && member.Guild == guild)
|
||||||
|
{
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guild.Members.TryGetValue(user.Id, out member!))
|
||||||
|
{
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await guild.GetMemberAsync(user.Id);
|
||||||
|
}
|
||||||
|
catch (NotFoundException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the user's username with the discriminator, in the format <c>username#discriminator</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The user whose username and discriminator to retrieve.</param>
|
||||||
|
/// <returns>A string in the format <c>username#discriminator</c></returns>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="user" /> is <see langword="null" />.</exception>
|
||||||
|
public static string GetUsernameWithDiscriminator(this DiscordUser user)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(user);
|
||||||
|
#else
|
||||||
|
if (user is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(user));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return $"{user.Username}#{user.Discriminator}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the current user is in the specified guild.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The user to check.</param>
|
||||||
|
/// <param name="guild">The guild whose member list to search.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if <paramref name="user" /> is a member of <paramref name="guild" />; otherwise,
|
||||||
|
/// <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
public static async Task<bool> IsInGuildAsync(this DiscordUser user, DiscordGuild guild)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(user);
|
||||||
|
ArgumentNullException.ThrowIfNull(guild);
|
||||||
|
#else
|
||||||
|
if (user is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (guild is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(guild));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (guild.Members.TryGetValue(user.Id, out _))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DiscordMember? member = await guild.GetMemberAsync(user.Id);
|
||||||
|
return member is not null;
|
||||||
|
}
|
||||||
|
catch (NotFoundException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalizes a <see cref="DiscordUser" /> so that the internal client is assured to be a specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The <see cref="DiscordUser" /> to normalize.</param>
|
||||||
|
/// <param name="client">The target client.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="DiscordUser" /> whose public values will match <paramref name="user" />, but whose internal client is
|
||||||
|
/// <paramref name="client" />.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="ArgumentNullException">
|
||||||
|
/// <para><paramref name="user" /> is <see langword="null" /></para>
|
||||||
|
/// -or-
|
||||||
|
/// <para><paramref name="client" /> is <see langword="null" /></para>
|
||||||
|
/// </exception>
|
||||||
|
public static async Task<DiscordGuild> NormalizeClientAsync(this DiscordUser user, DiscordClient client)
|
||||||
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
ArgumentNullException.ThrowIfNull(user);
|
||||||
|
ArgumentNullException.ThrowIfNull(client);
|
||||||
|
#else
|
||||||
|
if (user is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(client));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return await client.GetGuildAsync(user.Id);
|
||||||
|
}
|
||||||
|
}
|
61
X10D.Hosting/X10D.Hosting.csproj
Normal file
61
X10D.Hosting/X10D.Hosting.csproj
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFrameworks>net6.0;netstandard2.1</TargetFrameworks>
|
||||||
|
<LangVersion>10.0</LangVersion>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<ImplicitUsings>true</ImplicitUsings>
|
||||||
|
<Authors>Oliver Booth</Authors>
|
||||||
|
<NeutralLanguage>en</NeutralLanguage>
|
||||||
|
<RepositoryUrl>https://github.com/oliverbooth/X10D</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<Description>Extension methods on crack.</Description>
|
||||||
|
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
|
||||||
|
<PackageIcon>icon.png</PackageIcon>
|
||||||
|
<PackageIconUrl/>
|
||||||
|
<PackageTags>dotnet extension-methods</PackageTags>
|
||||||
|
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
|
||||||
|
<VersionPrefix>3.2.0</VersionPrefix>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' == ''">
|
||||||
|
<Version>$(VersionPrefix)-$(VersionSuffix)</Version>
|
||||||
|
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
|
||||||
|
<FileVersion>$(VersionPrefix).0</FileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' != ''">
|
||||||
|
<Version>$(VersionPrefix)-$(VersionSuffix).$(BuildNumber)</Version>
|
||||||
|
<AssemblyVersion>$(VersionPrefix).$(BuildNumber)</AssemblyVersion>
|
||||||
|
<FileVersion>$(VersionPrefix).$(BuildNumber)</FileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(VersionSuffix)' == ''">
|
||||||
|
<Version>$(VersionPrefix)</Version>
|
||||||
|
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
|
||||||
|
<FileVersion>$(VersionPrefix).0</FileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\icon.png">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath/>
|
||||||
|
</None>
|
||||||
|
<None Include="..\LICENSE.md">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath/>
|
||||||
|
</None>
|
||||||
|
<None Include="..\CHANGELOG.md">
|
||||||
|
<Pack>True</Pack>
|
||||||
|
<PackagePath/>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,35 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
namespace X10D.Hosting.DependencyInjection;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dependency injection extensions for <see cref="IServiceCollection" />.
|
||||||
|
/// </summary>
|
||||||
|
public static class ServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an <see cref="IHostedService" /> registration for the given type, while simultaneously adding it as a singleton.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services">The <see cref="IServiceCollection" /> to add the service to.</param>
|
||||||
|
/// <typeparam name="TService">The type of the service to add.</typeparam>
|
||||||
|
/// <returns>A reference to this instance after the operation has completed.</returns>
|
||||||
|
public static IServiceCollection AddHostedSingleton<TService>(this IServiceCollection services)
|
||||||
|
where TService : class, IHostedService
|
||||||
|
{
|
||||||
|
services.AddSingleton<TService>();
|
||||||
|
return services.AddSingleton<IHostedService, TService>(provider => provider.GetRequiredService<TService>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an <see cref="IHostedService" /> registration for the given type, while simultaneously adding it as a singleton.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services">The <see cref="IServiceCollection" /> to add the service to.</param>
|
||||||
|
/// <param name="type">The type of the service to register and the implementation to use.</param>
|
||||||
|
/// <returns>A reference to this instance after the operation has completed.</returns>
|
||||||
|
public static IServiceCollection AddHostedSingleton(this IServiceCollection services, Type type)
|
||||||
|
{
|
||||||
|
services.AddSingleton(type);
|
||||||
|
return services.AddSingleton(provider => (IHostedService)provider.GetRequiredService(type));
|
||||||
|
}
|
||||||
|
}
|
12
X10D.sln
12
X10D.sln
@ -24,6 +24,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.Unity", "X10D.Unity\X1
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.SourceGenerator", "X10D.SourceGenerator\X10D.SourceGenerator.csproj", "{077A5D33-AD55-4C55-8A67-972CEBC32C7A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.SourceGenerator", "X10D.SourceGenerator\X10D.SourceGenerator.csproj", "{077A5D33-AD55-4C55-8A67-972CEBC32C7A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.DSharpPlus", "X10D.DSharpPlus\X10D.DSharpPlus.csproj", "{675D3B25-7EA0-4FC3-B513-8DF27874F2CF}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.Hosting", "X10D.Hosting\X10D.Hosting.csproj", "{B04AF429-30CF-4B69-81BA-38F560CA9126}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -50,6 +54,14 @@ Global
|
|||||||
{077A5D33-AD55-4C55-8A67-972CEBC32C7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{077A5D33-AD55-4C55-8A67-972CEBC32C7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{077A5D33-AD55-4C55-8A67-972CEBC32C7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{077A5D33-AD55-4C55-8A67-972CEBC32C7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{077A5D33-AD55-4C55-8A67-972CEBC32C7A}.Release|Any CPU.Build.0 = Release|Any CPU
|
{077A5D33-AD55-4C55-8A67-972CEBC32C7A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{675D3B25-7EA0-4FC3-B513-8DF27874F2CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{675D3B25-7EA0-4FC3-B513-8DF27874F2CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{675D3B25-7EA0-4FC3-B513-8DF27874F2CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{675D3B25-7EA0-4FC3-B513-8DF27874F2CF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B04AF429-30CF-4B69-81BA-38F560CA9126}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B04AF429-30CF-4B69-81BA-38F560CA9126}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B04AF429-30CF-4B69-81BA-38F560CA9126}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B04AF429-30CF-4B69-81BA-38F560CA9126}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
Loading…
Reference in New Issue
Block a user