diff --git a/.gitignore b/.gitignore index 02a1e37..36fd0be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /.vscode /.claude /build +/release /.vs /tools diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..62fcb10 --- /dev/null +++ b/build.sh @@ -0,0 +1,94 @@ +#!/usr/bin/env bash +# Builds every server RID, packs the NuGet packages and collects the results in ./release. +# +# Server archives follow the build.cake naming so the artifacts match what CI publishes: +# Empostor-Server__.zip (win-x64) +# Empostor-Server__.tar.gz (linux-*, osx-x64) +# +# Note: Git Bash here has no `zip` binary, only `unzip`, so the win-x64 zip is produced by the +# small dotnet helper in tools/zipdir. tar handles the .tar.gz side natively. +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +OUT="$ROOT/release" +SERVER_PROJ="$ROOT/src/Empostor.Server/Empostor.Server.csproj" +API_PROJ="$ROOT/src/Empostor.Api/Empostor.Api.csproj" +SERVER_BIN="$ROOT/src/Empostor.Server/bin/Release/net8.0" +API_BIN="$ROOT/src/Empostor.Api/bin/Release" + +# Version comes from the props file, the same source build.cake reads. +VERSION="$(sed -n 's:.*\(.*\).*:\1:p' "$ROOT/src/Directory.Build.props" | head -1)" +if [ -z "$VERSION" ]; then + echo "error: could not read VersionPrefix from src/Directory.Build.props" >&2 + exit 1 +fi + +# Windows is the only zip target; everything else is tar.gz. +RIDS_ZIP="win-x64" +RIDS_TGZ="linux-x64 linux-arm64 linux-arm osx-x64" + +echo "==> Version $VERSION" +echo "==> Output $OUT" +rm -rf "$OUT" +mkdir -p "$OUT" + +# ---------------------------------------------------------------- server +for rid in $RIDS_ZIP $RIDS_TGZ; do + echo "==> Publishing server ($rid)" + dotnet publish "$SERVER_PROJ" -c Release -r "$rid" --nologo -v minimal +done + +# ---------------------------------------------------------------- api +echo "==> Packing Empostor.Api" +dotnet pack "$API_PROJ" -c Release --nologo -v minimal + +# ---------------------------------------------------------------- collect +# Build the zip helper once up front: `dotnet run` swallows --nologo/-v as its own options, so +# the app arguments only survive when they follow a bare `--`. +echo "==> Building zip helper" +dotnet build "$ROOT/tools/zipdir/zipdir.csproj" -c Release --nologo -v quiet + +# The publish step leaves a zip behind from an earlier build.cake run; use only the RID folders. +for rid in $RIDS_ZIP; do + dir="$SERVER_BIN/$rid/publish" + if [ ! -d "$dir" ]; then + echo "error: missing publish output $dir" >&2 + exit 1 + fi + echo "==> Zipping server ($rid)" + dotnet "$ROOT/tools/zipdir/bin/Release/net8.0/zipdir.dll" \ + "$dir" "$OUT/Empostor-Server_${VERSION}_${rid}.zip" +done + +for rid in $RIDS_TGZ; do + dir="$SERVER_BIN/$rid/publish" + if [ ! -d "$dir" ]; then + echo "error: missing publish output $dir" >&2 + exit 1 + fi + echo "==> Tarball server ($rid)" + # -C publishes the folder's contents, so the archive has no wrapping directory. + tar -czf "$OUT/Empostor-Server_${VERSION}_${rid}.tar.gz" -C "$dir" . +done + +# Only the release build (no -dev / -ci suffix) is collected; the others are stale local output. +echo "==> Collecting NuGet packages" +shopt -s nullglob +found=0 +for pkg in "$API_BIN"/Empostor.Api.*.nupkg "$API_BIN"/Empostor.Api.*.snupkg; do + name="$(basename "$pkg")" + case "$name" in + *-dev.nupkg|*-dev.snupkg|*-ci.*.nupkg|*-ci.*.snupkg) continue ;; + esac + cp -f "$pkg" "$OUT/" + found=1 +done +shopt -u nullglob +if [ "$found" -eq 0 ]; then + echo "error: no release NuGet package found in $API_BIN" >&2 + exit 1 +fi + +echo +echo "==> Done. Contents of release/:" +ls -lh "$OUT" diff --git a/marketplace/Empostor.Plugin.Code.dll b/marketplace/Empostor.Plugin.Code.dll index 9e7b6c1..68840a0 100644 Binary files a/marketplace/Empostor.Plugin.Code.dll and b/marketplace/Empostor.Plugin.Code.dll differ diff --git a/marketplace/Empostor.Plugins.DiscordWebhook.dll b/marketplace/Empostor.Plugins.DiscordWebhook.dll index 5f1fdb3..c55cf23 100644 Binary files a/marketplace/Empostor.Plugins.DiscordWebhook.dll and b/marketplace/Empostor.Plugins.DiscordWebhook.dll differ diff --git a/marketplace/Empostor.Plugins.FriendCodeValidator.dll b/marketplace/Empostor.Plugins.FriendCodeValidator.dll index 72f0859..0f9d6b6 100644 Binary files a/marketplace/Empostor.Plugins.FriendCodeValidator.dll and b/marketplace/Empostor.Plugins.FriendCodeValidator.dll differ diff --git a/marketplace/Empostor.Plugins.Maintenance.dll b/marketplace/Empostor.Plugins.Maintenance.dll new file mode 100644 index 0000000..07f5421 Binary files /dev/null and b/marketplace/Empostor.Plugins.Maintenance.dll differ diff --git a/marketplace/Empostor.Plugins.Monitor.dll b/marketplace/Empostor.Plugins.Monitor.dll index c633e28..5ce227b 100644 Binary files a/marketplace/Empostor.Plugins.Monitor.dll and b/marketplace/Empostor.Plugins.Monitor.dll differ diff --git a/marketplace/Empostor.Plugins.PlayerChannel.dll b/marketplace/Empostor.Plugins.PlayerChannel.dll index d945794..f70a5ca 100644 Binary files a/marketplace/Empostor.Plugins.PlayerChannel.dll and b/marketplace/Empostor.Plugins.PlayerChannel.dll differ diff --git a/marketplace/Empostor.Plugins.PlayerLog.dll b/marketplace/Empostor.Plugins.PlayerLog.dll index 100cf16..e01ff39 100644 Binary files a/marketplace/Empostor.Plugins.PlayerLog.dll and b/marketplace/Empostor.Plugins.PlayerLog.dll differ diff --git a/marketplace/Empostor.Plugins.Privacy.dll b/marketplace/Empostor.Plugins.Privacy.dll index afa3756..97ac9f5 100644 Binary files a/marketplace/Empostor.Plugins.Privacy.dll and b/marketplace/Empostor.Plugins.Privacy.dll differ diff --git a/marketplace/Empostor.Plugins.QqVerify.dll b/marketplace/Empostor.Plugins.QqVerify.dll index a361512..1942d31 100644 Binary files a/marketplace/Empostor.Plugins.QqVerify.dll and b/marketplace/Empostor.Plugins.QqVerify.dll differ diff --git a/marketplace/Empostor.Plugins.Titles.dll b/marketplace/Empostor.Plugins.Titles.dll index 08fc19c..b8432bc 100644 Binary files a/marketplace/Empostor.Plugins.Titles.dll and b/marketplace/Empostor.Plugins.Titles.dll differ diff --git a/marketplace/plugins.json b/marketplace/plugins.json index 217ec76..5560e06 100644 --- a/marketplace/plugins.json +++ b/marketplace/plugins.json @@ -7,7 +7,7 @@ "versions": [ { "version": "1.0.0", - "empostor_version": "2.0.0", + "empostor_version": "2.0.1", "download_url": "https://raw.githubusercontent.com/Empostor/Empostor/master/marketplace/Empostor.Plugin.Chat.dll" } ] @@ -20,7 +20,7 @@ "versions": [ { "version": "1.0.0", - "empostor_version": "2.0.0", + "empostor_version": "2.0.1", "download_url": "https://raw.githubusercontent.com/Empostor/Empostor/master/marketplace/Empostor.Plugin.Code.dll" } ] @@ -33,7 +33,7 @@ "versions": [ { "version": "1.0.0", - "empostor_version": "2.0.0", + "empostor_version": "2.0.1", "download_url": "https://raw.githubusercontent.com/Empostor/Empostor/master/marketplace/Empostor.Plugins.Welcome.dll" } ] @@ -59,7 +59,7 @@ "versions": [ { "version": "1.0.0", - "empostor_version": "2.0.0", + "empostor_version": "2.0.1", "download_url": "https://raw.githubusercontent.com/Empostor/Empostor/master/marketplace/Empostor.Plugins.FixedCode.dll" } ] @@ -150,7 +150,7 @@ "versions": [ { "version": "2.2.0", - "empostor_version": "2.0.0", + "empostor_version": "2.0.1", "download_url": "https://raw.githubusercontent.com/Empostor/Empostor/main/marketplace/Reactor.Empostor.dll" } ] @@ -176,7 +176,7 @@ "versions": [ { "version": "2.0.0", - "empostor_version": "2.0.0", + "empostor_version": "2.0.1", "download_url": "https://raw.githubusercontent.com/Empostor/Empostor/main/marketplace/Empostor.Plugins.DiscordWebhook.dll" } ] @@ -232,5 +232,18 @@ "download_url": "https://raw.githubusercontent.com/Empostor/Empostor/main/marketplace/Empostor.Plugins.Privacy.dll" } ] + }, + { + "id": "cn.hayashiume.maintenance", + "name": "Maintenance Server", + "description": "Maintian server to refuse plater connect to the server", + "author": "Empostor", + "versions": [ + { + "version": "1.0.0", + "empostor_version": "2.0.1", + "download_url": "https://raw.githubusercontent.com/Empostor/Empostor/main/marketplace/Empostor.Plugins.Maintenance.dll" + } + ] } ] diff --git a/src/Empostor.Plugins.Maintenance/Empostor.Plugins.Maintenance.csproj b/src/Empostor.Plugins.Maintenance/Empostor.Plugins.Maintenance.csproj new file mode 100644 index 0000000..0ae947b --- /dev/null +++ b/src/Empostor.Plugins.Maintenance/Empostor.Plugins.Maintenance.csproj @@ -0,0 +1,13 @@ + + + net8.0 + Empostor.Plugins.Maintenance + enable + + + + + + + + diff --git a/src/Empostor.Plugins.Maintenance/MaintenanceAdminExtension.cs b/src/Empostor.Plugins.Maintenance/MaintenanceAdminExtension.cs new file mode 100644 index 0000000..d5f39e8 --- /dev/null +++ b/src/Empostor.Plugins.Maintenance/MaintenanceAdminExtension.cs @@ -0,0 +1,78 @@ +using System; +using System.Threading.Tasks; +using Empostor.Api.Admin; + +namespace Empostor.Plugins.Maintenance; + +public sealed class MaintenanceAdminExtension : IAdminExtension +{ + private readonly MaintenanceStore _store; + private readonly MaintenanceListener _listener; + + public MaintenanceAdminExtension(MaintenanceStore store, MaintenanceListener listener) + { + _store = store; + _listener = listener; + } + + public string Id => "maintenance"; + + public string Title => "Maintenance"; + + public string Icon => "shield"; + + public void Build(AdminPanelBuilder b) + { + b.RegisterText( + _store.Enabled + ? "Maintenance mode: ON — every player is turned away." + : "Maintenance mode: OFF — the server is accepting players.", + _store.Enabled ? "warning" : "default"); + + b.RegisterButton(button => + { + button.Label = _store.Enabled ? "Turn maintenance OFF" : "Turn maintenance ON"; + button.Icon = _store.Enabled ? "refresh" : "shield"; + button.Style = _store.Enabled ? "primary" : "danger"; + button.OnClick(async ctx => await ToggleAsync(ctx)); + }); + + b.RegisterDivider(); + + b.RegisterTextbox(textbox => + { + textbox.Label = "Kick message (Chinese)"; + textbox.Value = _store.MessageZh; + textbox.Multiline = true; + textbox.OnSubmit(async ctx => await SaveMessageAsync(ctx, zh: ctx.Value, en: null)); + }); + + b.RegisterTextbox(textbox => + { + textbox.Label = "Kick message (English)"; + textbox.Value = _store.MessageEn; + textbox.Multiline = true; + textbox.OnSubmit(async ctx => await SaveMessageAsync(ctx, zh: null, en: ctx.Value)); + }); + } + + private async ValueTask ToggleAsync(AdminActionContext ctx) + { + var enabled = !_store.Enabled; + await _listener.SetAsync(enabled); + + return AdminActionResult.Ok(enabled + ? "Maintenance mode ON. Everyone in a lobby was disconnected; new players are refused." + : "Maintenance mode OFF. The server is accepting players again."); + } + + private async ValueTask SaveMessageAsync(AdminActionContext ctx, string? zh, string? en) + { + _store.SetMessages( + string.IsNullOrWhiteSpace(zh) ? _store.MessageZh : zh.Trim(), + string.IsNullOrWhiteSpace(en) ? _store.MessageEn : en.Trim()); + + await _store.SaveAsync(); + return AdminActionResult.Ok("Kick message saved."); + } +} diff --git a/src/Empostor.Plugins.Maintenance/MaintenanceListener.cs b/src/Empostor.Plugins.Maintenance/MaintenanceListener.cs new file mode 100644 index 0000000..a73f2bb --- /dev/null +++ b/src/Empostor.Plugins.Maintenance/MaintenanceListener.cs @@ -0,0 +1,102 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Empostor.Api.Events; +using Empostor.Api.Events.Client; +using Empostor.Api.Games; +using Empostor.Api.Games.Managers; +using Empostor.Api.Innersloth; +using Empostor.Api.Net; +using Microsoft.Extensions.Logging; + +namespace Empostor.Plugins.Maintenance; + +/// +/// While maintenance mode is on, every player is turned away: the ones already in a lobby are +/// disconnected, and anyone connecting, creating a lobby or trying to join is rejected with the +/// same message. +/// +public sealed class MaintenanceListener : IEventListener +{ + private readonly ILogger _logger; + private readonly MaintenanceStore _store; + private readonly IGameManager _games; + + public MaintenanceListener( + ILogger logger, + MaintenanceStore store, + IGameManager games) + { + _logger = logger; + _store = store; + _games = games; + } + + /// Turns maintenance on or off, disconnecting everyone currently in a lobby when on. + public async ValueTask SetAsync(bool enabled) + { + _store.SetEnabled(enabled); + await _store.SaveAsync(); + + if (!enabled) + { + _logger.LogInformation("MaintenanceMode disabled, the server is accepting players again"); + return; + } + + _logger.LogWarning("MaintenanceMode enabled, disconnecting every player currently in a lobby"); + await KickAllAsync(); + } + + private async ValueTask KickAllAsync() + { + foreach (var game in _games.Games.ToList()) + { + foreach (var player in game.Players.ToList()) + { + var client = player.Client; + if (client == null) + { + continue; + } + + try + { + await client.DisconnectAsync(DisconnectReason.Custom, _store.MessageFor(client.Language)); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Maintenance failed to disconnect client {Id}", client.Id); + } + } + } + } + + [EventListener] + public async ValueTask OnClientConnected(IClientConnectedEvent e) + { + // A client that never reaches a lobby would otherwise sit connected forever. + if (_store.Enabled) + { + await e.Client.DisconnectAsync(DisconnectReason.Custom, _store.MessageFor(e.Client.Language)); + } + } + + [EventListener] + public async ValueTask OnGameCreating(IGameCreationEvent e) + { + if (_store.Enabled && e.Client != null) + { + await e.Client.DisconnectAsync(DisconnectReason.Custom, _store.MessageFor(e.Client.Language)); + } + } + + [EventListener] + public void OnPlayerJoining(IGamePlayerJoiningEvent e) + { + if (_store.Enabled) + { + e.JoinResult = GameJoinResult.CreateCustomError(_store.MessageFor(e.Player.Client.Language)); + } + } +} diff --git a/src/Empostor.Plugins.Maintenance/MaintenancePlugin.cs b/src/Empostor.Plugins.Maintenance/MaintenancePlugin.cs new file mode 100644 index 0000000..f06848e --- /dev/null +++ b/src/Empostor.Plugins.Maintenance/MaintenancePlugin.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; +using Empostor.Api.Plugins; +using Microsoft.Extensions.Logging; + +namespace Empostor.Plugins.Maintenance; + +[EmpostorPlugin("cn.hayashiume.maintenance")] +public sealed class MaintenancePlugin : PluginBase +{ + private readonly ILogger _logger; + + public MaintenancePlugin(ILogger logger) + { + _logger = logger; + } + + public override ValueTask EnableAsync() + { + _logger.LogInformation("[Maintenance] Plugin enabled. Use the admin panel (Plugins → Maintenance) to toggle maintenance mode."); + return default; + } + + public override ValueTask DisableAsync() => default; +} diff --git a/src/Empostor.Plugins.Maintenance/MaintenanceStartup.cs b/src/Empostor.Plugins.Maintenance/MaintenanceStartup.cs new file mode 100644 index 0000000..1015945 --- /dev/null +++ b/src/Empostor.Plugins.Maintenance/MaintenanceStartup.cs @@ -0,0 +1,22 @@ +using Empostor.Api.Admin; +using Empostor.Api.Events; +using Empostor.Api.Plugins; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Empostor.Plugins.Maintenance; + +public sealed class MaintenanceStartup : IPluginStartup +{ + public void ConfigureHost(IHostBuilder host) { } + + public void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(sp => sp.GetRequiredService()); + services.AddSingleton(sp => new MaintenanceAdminExtension( + sp.GetRequiredService(), + sp.GetRequiredService())); + } +} diff --git a/src/Empostor.Plugins.Maintenance/MaintenanceStore.cs b/src/Empostor.Plugins.Maintenance/MaintenanceStore.cs new file mode 100644 index 0000000..39c48aa --- /dev/null +++ b/src/Empostor.Plugins.Maintenance/MaintenanceStore.cs @@ -0,0 +1,65 @@ +using System.Threading.Tasks; +using Empostor.Api.Innersloth; +using Empostor.Api.Service; +using Microsoft.Extensions.Logging; + +namespace Empostor.Plugins.Maintenance; + +public sealed class MaintenanceConfig +{ + public bool Enabled { get; set; } + + public string MessageZh { get; set; } = "服务器正在维护中,请联系管理员获取支持。"; + + public string MessageEn { get; set; } = "The server is under maintenance. Please contact the administrator for support."; +} + +/// +/// Holds the maintenance flag and the two kick messages. Persisted so a restart does not +/// silently drop the server back into service while an operator is mid-update. +/// +public sealed class MaintenanceStore : JsonDataStore +{ + public MaintenanceStore(ILogger logger) + : base(logger) + { + Load(); + } + + public bool Enabled { get; private set; } + + public string MessageZh { get; private set; } = new MaintenanceConfig().MessageZh; + + public string MessageEn { get; private set; } = new MaintenanceConfig().MessageEn; + + /// The message shown to a client speaking the given language. + public string MessageFor(Language language) => language switch + { + Language.SChinese or Language.TChinese => MessageZh, + _ => MessageEn, + }; + + public void SetEnabled(bool enabled) => Enabled = enabled; + + public void SetMessages(string zh, string en) + { + MessageZh = zh; + MessageEn = en; + } + + public new async ValueTask SaveAsync() => await base.SaveAsync(); + + protected override MaintenanceConfig GetSnapshot() => new() + { + Enabled = Enabled, + MessageZh = MessageZh, + MessageEn = MessageEn, + }; + + protected override void ApplySnapshot(MaintenanceConfig data) + { + Enabled = data.Enabled; + MessageZh = data.MessageZh; + MessageEn = data.MessageEn; + } +} diff --git a/src/Empostor.Plugins.Maintenance/packages.lock.json b/src/Empostor.Plugins.Maintenance/packages.lock.json new file mode 100644 index 0000000..5763b34 --- /dev/null +++ b/src/Empostor.Plugins.Maintenance/packages.lock.json @@ -0,0 +1,140 @@ +{ + "version": 1, + "dependencies": { + "net8.0": { + "BouncyCastle.Cryptography": { + "type": "Transitive", + "resolved": "2.6.1", + "contentHash": "vZsG2YILhthgRqO+ZVgRff4ZFKKTl0v7kqaVBLCtRvpREhfBP33pcWrdA3PRYgWuFL1RxiUFvjMUHTdBZlJcoA==" + }, + "Empostor.Hazel": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "cblWCgvLcQ2xK6ztV04RVrghVEnJpCWe4N6G3LCNaJhuUq367a1/bbtQxUWAflqvgSvGwY3g3SClhh9eWTCBDA==", + "dependencies": { + "BouncyCastle.Cryptography": "2.6.1", + "Empostor.Hazel.Abstractions": "1.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.6", + "Microsoft.Extensions.ObjectPool": "8.0.1", + "Serilog": "4.3.1" + } + }, + "Empostor.Hazel.Abstractions": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "uJqGMASOGj+ELffmIMqubyvJ/FHjOXA1RtQdS38s1LRhP+Eu4zJMTTndr12+Q3vS0kHggFFyuExFmNxWyzWmig==" + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.2.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.2.0", + "contentHash": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.2.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "9.0.6", + "contentHash": "0Zn6nR/6g+90MxskZyOOMPQvnPnrrGu6bytPwkV+azDcTtCSuQ1+GJUrg8Klmnrjk1i6zMpw2lXijl+tw7Q3kA==" + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "JHYCQG7HmugNYUhOl368g+NMxYE/N/AiclCYRNlgCY9eVyiBkOHMwK4x60RYMxv9EL3+rmj1mqHvdCiPpC+D4Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "System.Diagnostics.DiagnosticSource": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "AG7HWwVRdCHlaA++1oKDxLsXIBxmDpMPb3VoyOoAghEWnkUvEAdYQUwnV4jJbAaa/nMYNiEh5ByoLauZBEiovg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.ObjectPool": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "X21b8D6z58EG34OMLH955750mFaEaGs5xLGe9Vyi3059Cgb3sk+p2k/JlQXaieEBRrk+SVlFzDei3Q6PdVzJOA==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "JOVOfqpnqlVLUzINQ2fox8evY2SKLYJ3BV8QDe/Jyp21u1T7r45x/R/5QdteURMR5r01GxeJSBBUOCOyaNXA3g==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Serilog": { + "type": "Transitive", + "resolved": "4.3.1", + "contentHash": "savYe7h5yRlkqBVOwP8cIRDOdqKiPmYCU4W87JH38sBmcKD5EBoXvQIw6bNEvZ/pTe1gsiye3VFCzBsoppGkXQ==" + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "c9xLpVz6PL9lp/djOWtk5KPDZq3cSYpmXoJQY524EOtuFl5z9ZtsotpsyrDW40U1DRnQSYvcPKEUV0X//u6gkQ==" + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "Xg4G4Indi4dqP1iuAiMSwpiWS54ZghzR644OtsRCm/m/lBMG8dUBhLVN7hLm8NNrNTR+iGbshCPTwrvxZPlm4g==" + }, + "empostor.api": { + "type": "Project", + "dependencies": { + "Empostor.Hazel": "[1.0.2, )", + "Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, )", + "Microsoft.Extensions.Hosting.Abstractions": "[8.0.0, )", + "Microsoft.Extensions.Logging.Abstractions": "[8.0.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/src/Empostor.sln b/src/Empostor.sln index 5bcb53d..332780a 100644 --- a/src/Empostor.sln +++ b/src/Empostor.sln @@ -47,6 +47,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Empostor.Plugins.Monitor", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Empostor.Plugins.Privacy", "Empostor.Plugins.Privacy\Empostor.Plugins.Privacy.csproj", "{959879FE-2FE0-4FD8-A706-0FA1B3138F45}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Empostor.Plugins.Maintenance", "Empostor.Plugins.Maintenance\Empostor.Plugins.Maintenance.csproj", "{79F25D71-B209-4B6B-89FF-54999A93D9E2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -309,6 +311,18 @@ Global {959879FE-2FE0-4FD8-A706-0FA1B3138F45}.Release|x64.Build.0 = Release|Any CPU {959879FE-2FE0-4FD8-A706-0FA1B3138F45}.Release|x86.ActiveCfg = Release|Any CPU {959879FE-2FE0-4FD8-A706-0FA1B3138F45}.Release|x86.Build.0 = Release|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Debug|x64.ActiveCfg = Debug|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Debug|x64.Build.0 = Debug|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Debug|x86.ActiveCfg = Debug|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Debug|x86.Build.0 = Debug|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Release|Any CPU.Build.0 = Release|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Release|x64.ActiveCfg = Release|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Release|x64.Build.0 = Release|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Release|x86.ActiveCfg = Release|Any CPU + {79F25D71-B209-4B6B-89FF-54999A93D9E2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -332,6 +346,7 @@ Global {135D8F7F-C330-444E-94D4-D2D3944F688A} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29} {B50665B5-AEDB-4F56-B54A-542863EDB009} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29} {959879FE-2FE0-4FD8-A706-0FA1B3138F45} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29} + {79F25D71-B209-4B6B-89FF-54999A93D9E2} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DAF5625C-7E46-4DCC-AF2C-11D20D965454}