mirror of
https://github.com/Empostor/Empostor.git
synced 2026-10-19 15:51:39 +00:00
Update Plugins
This commit is contained in:
1 parent
8eaf33595b
commit
6fd771e0cf
21 files changed
+573
-6
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
/.vscode
|
/.vscode
|
||||||
/.claude
|
/.claude
|
||||||
/build
|
/build
|
||||||
|
/release
|
||||||
/.vs
|
/.vs
|
||||||
/tools
|
/tools
|
||||||
|
|
||||||
|
|||||||
@@ -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_<version>_<rid>.zip (win-x64)
|
||||||
|
# Empostor-Server_<version>_<rid>.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:.*<VersionPrefix>\(.*\)</VersionPrefix>.*:\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"
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,7 +7,7 @@
|
|||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"version": "1.0.0",
|
"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"
|
"download_url": "https://raw.githubusercontent.com/Empostor/Empostor/master/marketplace/Empostor.Plugin.Chat.dll"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"version": "1.0.0",
|
"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"
|
"download_url": "https://raw.githubusercontent.com/Empostor/Empostor/master/marketplace/Empostor.Plugin.Code.dll"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"version": "1.0.0",
|
"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"
|
"download_url": "https://raw.githubusercontent.com/Empostor/Empostor/master/marketplace/Empostor.Plugins.Welcome.dll"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"version": "1.0.0",
|
"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"
|
"download_url": "https://raw.githubusercontent.com/Empostor/Empostor/master/marketplace/Empostor.Plugins.FixedCode.dll"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -150,7 +150,7 @@
|
|||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"version": "2.2.0",
|
"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"
|
"download_url": "https://raw.githubusercontent.com/Empostor/Empostor/main/marketplace/Reactor.Empostor.dll"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -176,7 +176,7 @@
|
|||||||
"versions": [
|
"versions": [
|
||||||
{
|
{
|
||||||
"version": "2.0.0",
|
"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"
|
"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"
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<AssemblyName>Empostor.Plugins.Maintenance</AssemblyName>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Empostor.Api\Empostor.Api.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Target Name="CopyToMarketplace" AfterTargets="Build">
|
||||||
|
<Copy SourceFiles="$(TargetPath)" DestinationFolder="E:\WindowsFile\Empostor\Empostor\marketplace" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
@@ -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<AdminActionResult> 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<AdminActionResult> 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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MaintenanceListener : IEventListener
|
||||||
|
{
|
||||||
|
private readonly ILogger<MaintenanceListener> _logger;
|
||||||
|
private readonly MaintenanceStore _store;
|
||||||
|
private readonly IGameManager _games;
|
||||||
|
|
||||||
|
public MaintenanceListener(
|
||||||
|
ILogger<MaintenanceListener> logger,
|
||||||
|
MaintenanceStore store,
|
||||||
|
IGameManager games)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_store = store;
|
||||||
|
_games = games;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Turns maintenance on or off, disconnecting everyone currently in a lobby when on.</summary>
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<MaintenancePlugin> _logger;
|
||||||
|
|
||||||
|
public MaintenancePlugin(ILogger<MaintenancePlugin> 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;
|
||||||
|
}
|
||||||
@@ -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<MaintenanceStore>();
|
||||||
|
services.AddSingleton<MaintenanceListener>();
|
||||||
|
services.AddSingleton<IEventListener>(sp => sp.GetRequiredService<MaintenanceListener>());
|
||||||
|
services.AddSingleton<IAdminExtension>(sp => new MaintenanceAdminExtension(
|
||||||
|
sp.GetRequiredService<MaintenanceStore>(),
|
||||||
|
sp.GetRequiredService<MaintenanceListener>()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class MaintenanceStore : JsonDataStore<MaintenanceConfig>
|
||||||
|
{
|
||||||
|
public MaintenanceStore(ILogger<MaintenanceStore> 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;
|
||||||
|
|
||||||
|
/// <summary>The message shown to a client speaking the given language.</summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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, )"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,6 +47,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Empostor.Plugins.Monitor",
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Empostor.Plugins.Privacy", "Empostor.Plugins.Privacy\Empostor.Plugins.Privacy.csproj", "{959879FE-2FE0-4FD8-A706-0FA1B3138F45}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Empostor.Plugins.Privacy", "Empostor.Plugins.Privacy\Empostor.Plugins.Privacy.csproj", "{959879FE-2FE0-4FD8-A706-0FA1B3138F45}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Empostor.Plugins.Maintenance", "Empostor.Plugins.Maintenance\Empostor.Plugins.Maintenance.csproj", "{79F25D71-B209-4B6B-89FF-54999A93D9E2}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
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|x64.Build.0 = Release|Any CPU
|
||||||
{959879FE-2FE0-4FD8-A706-0FA1B3138F45}.Release|x86.ActiveCfg = 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
|
{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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -332,6 +346,7 @@ Global
|
|||||||
{135D8F7F-C330-444E-94D4-D2D3944F688A} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29}
|
{135D8F7F-C330-444E-94D4-D2D3944F688A} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29}
|
||||||
{B50665B5-AEDB-4F56-B54A-542863EDB009} = {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}
|
{959879FE-2FE0-4FD8-A706-0FA1B3138F45} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29}
|
||||||
|
{79F25D71-B209-4B6B-89FF-54999A93D9E2} = {E0009DCB-32A6-45C4-A06C-7F62D4091A29}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {DAF5625C-7E46-4DCC-AF2C-11D20D965454}
|
SolutionGuid = {DAF5625C-7E46-4DCC-AF2C-11D20D965454}
|
||||||
|
|||||||
Reference in new issue
Block a user