Updated EllieHub to 1.0.1.0
This commit is contained in:
parent
50f40f01d1
commit
fe5c273143
8 changed files with 114 additions and 90 deletions
|
@ -95,19 +95,16 @@ public static class AppResources
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string LightBackground = "LightBackground";
|
public const string LightBackground = "LightBackground";
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resource type: <see cref="ImmutableSolidColorBrush"/>
|
/// Resource type: <see cref="ImmutableSolidColorBrush"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string MediumBackground = "MediumBackground";
|
public const string MediumBackground = "MediumBackground";
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resource type: <see cref="ImmutableSolidColorBrush"/>
|
/// Resource type: <see cref="ImmutableSolidColorBrush"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string HeavyBackground = "HeavyBackground";
|
public const string HeavyBackground = "HeavyBackground";
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resource type: <see cref="ImmutableSolidColorBrush"/>
|
/// Resource type: <see cref="ImmutableSolidColorBrush"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,41 +1,42 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!--Project Settings-->
|
<!--Project Settings-->
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<AnalysisLevel>latest</AnalysisLevel>
|
<AnalysisLevel>latest</AnalysisLevel>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<WarningsAsErrors>Nullable</WarningsAsErrors>
|
<WarningsAsErrors>Nullable</WarningsAsErrors>
|
||||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
<BuiltInComInteropSupport>True</BuiltInComInteropSupport>
|
<BuiltInComInteropSupport>True</BuiltInComInteropSupport>
|
||||||
<ApplicationIcon>Assets/Light/ellieupdatericon.ico</ApplicationIcon>
|
<ApplicationIcon>Assets/Light/ellieupdatericon.ico</ApplicationIcon>
|
||||||
|
|
||||||
<!--Publishing-->
|
|
||||||
<PublishSingleFile>true</PublishSingleFile>
|
|
||||||
<DebugType>embedded</DebugType>
|
|
||||||
|
|
||||||
<!--Version-->
|
<!--Publishing-->
|
||||||
<VersionPrefix>1.0.0.0</VersionPrefix>
|
<PublishSingleFile>true</PublishSingleFile>
|
||||||
|
<SelfContained>true</SelfContained>
|
||||||
<!--Avalonia Settings-->
|
<DebugType>embedded</DebugType>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
|
||||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
|
||||||
|
|
||||||
<!--Generate app host, so the final MacOS .app binary works-->
|
|
||||||
<UseAppHost>true</UseAppHost>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<!--Version-->
|
||||||
<AvaloniaResource Include="Assets\**" />
|
<VersionPrefix>1.0.1.0</VersionPrefix>
|
||||||
|
|
||||||
<!--Watch XAML files for hot reload-->
|
<!--Avalonia Settings-->
|
||||||
<Watch Include="**\*.xaml" />
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<Watch Include="**\*.axaml" />
|
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||||
</ItemGroup>
|
|
||||||
|
<!--Generate app host, so the final MacOS .app binary works-->
|
||||||
|
<UseAppHost>true</UseAppHost>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<AvaloniaResource Include="Assets\**" />
|
||||||
|
|
||||||
|
<!--Watch XAML files for hot reload-->
|
||||||
|
<Watch Include="**\*.xaml" />
|
||||||
|
<Watch Include="**\*.axaml" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.0.4" />
|
<PackageReference Include="Avalonia" Version="11.0.4" />
|
||||||
|
@ -54,9 +55,9 @@
|
||||||
<PackageReference Include="SkiaImageView.Avalonia11" Version="1.5.0" />
|
<PackageReference Include="SkiaImageView.Avalonia11" Version="1.5.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="Views\Windows\AppView.axaml.cs">
|
<Compile Update="Views\Windows\AppView.axaml.cs">
|
||||||
<DependentUpon>AppView.axaml</DependentUpon>
|
<DependentUpon>AppView.axaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -23,7 +23,7 @@ public sealed class AppResolver : IAppResolver
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public string FileName { get; }
|
public string FileName { get; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public string BinaryUri { get; }
|
public string BinaryUri { get; }
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ public sealed class AppResolver : IAppResolver
|
||||||
foreach (var newFileUri in newFilesUris)
|
foreach (var newFileUri in newFilesUris)
|
||||||
{
|
{
|
||||||
var destinationUri = Path.Combine(AppContext.BaseDirectory, newFileUri[(newFileUri.LastIndexOf(Path.DirectorySeparatorChar) + 1)..]);
|
var destinationUri = Path.Combine(AppContext.BaseDirectory, newFileUri[(newFileUri.LastIndexOf(Path.DirectorySeparatorChar) + 1)..]);
|
||||||
|
|
||||||
// Rename the original file from "file" to "file_old".
|
// Rename the original file from "file" to "file_old".
|
||||||
if (File.Exists(destinationUri))
|
if (File.Exists(destinationUri))
|
||||||
File.Move(destinationUri, destinationUri + OldFileSuffix);
|
File.Move(destinationUri, destinationUri + OldFileSuffix);
|
||||||
|
|
|
@ -30,12 +30,10 @@ public sealed class EllieOrchestrator : IBotOrchestrator
|
||||||
public EllieOrchestrator(ReadOnlyAppConfig appConfig)
|
public EllieOrchestrator(ReadOnlyAppConfig appConfig)
|
||||||
=> _appConfig = appConfig;
|
=> _appConfig = appConfig;
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool IsBotRunning(Guid botId)
|
public bool IsBotRunning(Guid botId)
|
||||||
=> _runningBots.ContainsKey(botId);
|
=> _runningBots.ContainsKey(botId);
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool Start(Guid botId)
|
public bool Start(Guid botId)
|
||||||
{
|
{
|
||||||
|
|
|
@ -162,52 +162,15 @@ public sealed partial class EllieResolver : IBotResolver
|
||||||
cToken
|
cToken
|
||||||
);
|
);
|
||||||
|
|
||||||
// Move the bot root directory while renaming it
|
// Move the bot root directory
|
||||||
if (Environment.OSVersion.Platform is not PlatformID.Unix)
|
if (Environment.OSVersion.Platform is not PlatformID.Unix)
|
||||||
{
|
await InstallToWindowsAsync(downloadStream, installationUri, zipTempLocation, botTempLocation, cToken);
|
||||||
// Save the zip file
|
|
||||||
using (var fileStream = new FileStream(zipTempLocation, FileMode.Create))
|
|
||||||
await downloadStream.CopyToAsync(fileStream, cToken);
|
|
||||||
|
|
||||||
// Extract the zip file
|
|
||||||
await Task.Run(() => ZipFile.ExtractToDirectory(zipTempLocation, _tempDirectory), cToken);
|
|
||||||
|
|
||||||
// Move the bot root directory while renaming it
|
|
||||||
Directory.Move(botTempLocation, installationUri);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
await InstallToUnixAsync(downloadStream, installationUri, botTempLocation, cToken);
|
||||||
// Extract the tar ball
|
|
||||||
await TarFile.ExtractToDirectoryAsync(downloadStream, _tempDirectory, true, cToken);
|
|
||||||
|
|
||||||
// Move the bot root directory with "mv" to circumvent this issue on Unix systems: https://github.com/dotnet/runtime/issues/31149
|
|
||||||
using var moveProcess = Utilities.StartProcess("mv", $"\"{botTempLocation}\" \"{installationUri}\"");
|
|
||||||
await moveProcess.WaitForExitAsync(cToken);
|
|
||||||
|
|
||||||
// Set executable permission
|
|
||||||
using var chmod = Utilities.StartProcess("chmod", $"+x \"{Path.Combine(installationUri, FileName)}\"");
|
|
||||||
await chmod.WaitForExitAsync(cToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reapply bot settings
|
// Reapply bot settings
|
||||||
if (File.Exists(backupFileUri))
|
if (File.Exists(backupFileUri))
|
||||||
{
|
await ReaplyBotSettingsAsync(installationUri, backupFileUri, cToken);
|
||||||
using var zipFile = ZipFile.OpenRead(backupFileUri);
|
|
||||||
var zippedFiles = zipFile.Entries
|
|
||||||
.Where(x =>
|
|
||||||
x.Name is "creds.yml" or "creds_example.yml"
|
|
||||||
|| (!string.IsNullOrWhiteSpace(x.Name) && x.FullName.Contains("data/"))
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach (var zippedFile in zippedFiles)
|
|
||||||
{
|
|
||||||
var fileDestinationPath = zippedFile.FullName.Split('/')
|
|
||||||
.Prepend(Directory.GetParent(installationUri)?.FullName ?? string.Empty)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
await RestoreFileAsync(zippedFile, Path.Combine(fileDestinationPath), cToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update settings
|
// Update settings
|
||||||
await _appConfigManager.UpdateBotEntryAsync(Id, x => x with { Version = latestVersion }, cToken);
|
await _appConfigManager.UpdateBotEntryAsync(Id, x => x with { Version = latestVersion }, cToken);
|
||||||
|
@ -230,6 +193,73 @@ public sealed partial class EllieResolver : IBotResolver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Installs the Nadeko instance on a Unix system.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="downloadStream">The stream of data downloaded from the source.</param>
|
||||||
|
/// <param name="installationUri">The absolute path to the directory the bot got installed to.</param>
|
||||||
|
/// <param name="botTempLocation">The absolute path to the temporary directory the bot is extracted to.</param>
|
||||||
|
/// <param name="cToken">The cancellation token.</param>
|
||||||
|
private async ValueTask InstallToUnixAsync(Stream downloadStream, string installationUri, string botTempLocation, CancellationToken cToken = default)
|
||||||
|
{
|
||||||
|
// Extract the tar ball
|
||||||
|
await TarFile.ExtractToDirectoryAsync(downloadStream, _tempDirectory, true, cToken);
|
||||||
|
|
||||||
|
// Move the bot root directory with "mv" to circumvent this issue on Unix systems: https://github.com/dotnet/runtime/issues/31149
|
||||||
|
using var moveProcess = Utilities.StartProcess("mv", $"\"{botTempLocation}\" \"{installationUri}\"");
|
||||||
|
await moveProcess.WaitForExitAsync(cToken);
|
||||||
|
|
||||||
|
// Set executable permission
|
||||||
|
using var chmod = Utilities.StartProcess("chmod", $"+x \"{Path.Combine(installationUri, FileName)}\"");
|
||||||
|
await chmod.WaitForExitAsync(cToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Installs the Nadeko instance on a non-Unix system.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="downloadStream">The stream of data downloaded from the source.</param>
|
||||||
|
/// <param name="installationUri">The absolute path to the directory the bot got installed to.</param>
|
||||||
|
/// <param name="zipTempLocation">The absolute path to the zip file the bot is initially on.</param>
|
||||||
|
/// <param name="botTempLocation">The absolute path to the temporary directory the bot is extracted to.</param>
|
||||||
|
/// <param name="cToken">The cancellation token.</param>
|
||||||
|
private async static ValueTask InstallToWindowsAsync(Stream downloadStream, string installationUri, string zipTempLocation, string botTempLocation, CancellationToken cToken = default)
|
||||||
|
{
|
||||||
|
// Save the zip file
|
||||||
|
using (var fileStream = new FileStream(zipTempLocation, FileMode.Create))
|
||||||
|
await downloadStream.CopyToAsync(fileStream, cToken);
|
||||||
|
|
||||||
|
// Extract the zip file
|
||||||
|
await Task.Run(() => ZipFile.ExtractToDirectory(zipTempLocation, _tempDirectory), cToken);
|
||||||
|
|
||||||
|
// Move the bot root directory while renaming it
|
||||||
|
Directory.Move(botTempLocation, installationUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reaplies the bot settings and user-defined data from the specified backup.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="installationUri">The absolute path to the directory the bot got installed to.</param>
|
||||||
|
/// <param name="backupFileUri">The absolute path to the backup zip file.</param>
|
||||||
|
/// <param name="cToken">The cancellation token.</param>
|
||||||
|
private async static ValueTask ReaplyBotSettingsAsync(string installationUri, string backupFileUri, CancellationToken cToken = default)
|
||||||
|
{
|
||||||
|
using var zipFile = ZipFile.OpenRead(backupFileUri);
|
||||||
|
var zippedFiles = zipFile.Entries
|
||||||
|
.Where(x =>
|
||||||
|
x.Name is "creds.yml" or "creds_example.yml"
|
||||||
|
|| (!string.IsNullOrWhiteSpace(x.Name) && x.FullName.Contains("data/"))
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach (var zippedFile in zippedFiles)
|
||||||
|
{
|
||||||
|
var fileDestinationPath = zippedFile.FullName.Split('/')
|
||||||
|
.Prepend(Directory.GetParent(installationUri)?.FullName ?? string.Empty)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
await RestoreFileAsync(zippedFile, Path.Combine(fileDestinationPath), cToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extracts the specified <paramref name="zippedFile"/> to the <paramref name="destinationPath"/>.
|
/// Extracts the specified <paramref name="zippedFile"/> to the <paramref name="destinationPath"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -48,7 +48,7 @@ public sealed class LogWriter : ILogWriter
|
||||||
var botEntry = _appConfig.BotEntries[botId];
|
var botEntry = _appConfig.BotEntries[botId];
|
||||||
var now = DateTimeOffset.Now;
|
var now = DateTimeOffset.Now;
|
||||||
var date = new DateOnly(now.Year, now.Month, now.Day).ToShortDateString().Replace('/', '-');
|
var date = new DateOnly(now.Year, now.Month, now.Day).ToShortDateString().Replace('/', '-');
|
||||||
var fileUri = Path.Combine(_appConfig.LogsDirectoryUri, $"{botEntry.Name}_{date}-{now.ToUnixTimeSeconds()}.txt");
|
var fileUri = Path.Combine(_appConfig.LogsDirectoryUri, $"{botEntry.Name}_v{botEntry.Version}_{date}-{now.ToUnixTimeSeconds()}.txt");
|
||||||
|
|
||||||
await File.WriteAllTextAsync(fileUri, logStringBuilder.ToString(), cToken);
|
await File.WriteAllTextAsync(fileUri, logStringBuilder.ToString(), cToken);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ using ReactiveUI;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace EllieHub.ViewModels.Controls;
|
namespace EllieHub.ViewModels.Controls;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
using MsBox.Avalonia.Enums;
|
using MsBox.Avalonia.Enums;
|
||||||
|
|
Loading…
Reference in a new issue