convert to c#

This commit is contained in:
2024-06-18 10:56:32 +02:00
parent f07fad0a80
commit deb14caf24
49 changed files with 1622 additions and 1534 deletions

View File

@@ -0,0 +1,40 @@
namespace ModpackUpdater.Manager;
public static class Extensions
{
public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive)
{
// Get information about the source directory
var dir = new DirectoryInfo(sourceDir);
// Check if the source directory exists
if (!dir.Exists)
throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
// Cache directories before we start copying
DirectoryInfo[] dirs = dir.GetDirectories();
// Create the destination directory
Directory.CreateDirectory(destinationDir);
// Get the files in the source directory and copy to the destination directory
foreach (FileInfo @file in dir.GetFiles())
{
string targetFilePath = Path.Combine(destinationDir, @file.Name);
@file.CopyTo(targetFilePath);
}
// If recursive and copying subdirectories, recursively call this method
if (recursive)
{
foreach (DirectoryInfo subDir in dirs)
{
string newDestinationDir = Path.Combine(destinationDir, subDir.Name);
CopyDirectory(subDir.FullName, newDestinationDir, true);
}
}
}
}

View File

@@ -1,35 +0,0 @@
Imports System.IO
Public Module Extensions
Public Sub CopyDirectory(sourceDir As String, destinationDir As String, recursive As Boolean)
' Get information about the source directory
Dim dir As New DirectoryInfo(sourceDir)
' Check if the source directory exists
If Not dir.Exists Then
Throw New DirectoryNotFoundException($"Source directory not found: {dir.FullName}")
End If
' Cache directories before we start copying
Dim dirs As DirectoryInfo() = dir.GetDirectories()
' Create the destination directory
Directory.CreateDirectory(destinationDir)
' Get the files in the source directory and copy to the destination directory
For Each file As FileInfo In dir.GetFiles()
Dim targetFilePath As String = Path.Combine(destinationDir, file.Name)
file.CopyTo(targetFilePath)
Next
' If recursive and copying subdirectories, recursively call this method
If recursive Then
For Each subDir As DirectoryInfo In dirs
Dim newDestinationDir As String = Path.Combine(destinationDir, subDir.Name)
CopyDirectory(subDir.FullName, newDestinationDir, True)
Next
End If
End Sub
End Module

View File

@@ -0,0 +1,11 @@
namespace ModpackUpdater.Manager;
public class MinecraftProfileChecker
{
public static bool CheckProfile(string folderPath)
{
// Todo: Adds some checks to verify, if the current folder is a minecraft folder.
return true;
}
}

View File

@@ -1,8 +0,0 @@
Public Class MinecraftProfileChecker
Public Shared Function CheckProfile(folderPath As string) As Boolean
'Todo: Adds some checks to verify, if the current folder is a minecraft folder.
Return True
End Function
End Class

View File

@@ -0,0 +1,211 @@
using ModpackUpdater.Model;
using System.IO.Compression;
namespace ModpackUpdater.Manager;
public class ModpackInstaller(ModpackConfig updateConfig, string localPath)
{
private class LocalZipCacheEntry
{
public string DownloadUrl { get; set; }
public string ExtractedZipPath { get; set; }
}
public event InstallProgessUpdatedEventHandler InstallProgessUpdated;
public delegate void InstallProgessUpdatedEventHandler(UpdateCheckResult result, int processedSyncs);
public event CheckingProgressUpdatedEventHandler CheckingProgressUpdated;
public delegate void CheckingProgressUpdatedEventHandler(int toCheck, int processed);
private HttpClient httpClient = new();
~ModpackInstaller()
{
httpClient.Dispose();
}
private async Task<UpdateInfos> DownloadUpdateInfos()
{
var content = await httpClient.GetStringAsync(updateConfig.UpdateUrl);
return UpdateInfos.Parse(content);
}
private async Task<InstallInfos> DownloadInstallInfos()
{
var content = await httpClient.GetStringAsync(updateConfig.InstallUrl);
return InstallInfos.Parse(content);
}
public async Task<UpdateCheckResult> Check(bool ignoreRevmoedFiles)
{
var result = new UpdateCheckResult();
if (ModpackInfo.HasModpackInfo(localPath))
{
var infos = await DownloadUpdateInfos();
var modpackInfo = ModpackInfo.Load(localPath);
if (infos is not null && infos.Updates.Count != 0)
{
var updatesOrderes = infos.Updates.OrderByDescending(n => n.Version);
result.LatestVersion = updatesOrderes.First().Version;
result.CurrentVersion = modpackInfo.Version;
result.IsInstalled = true;
var checkingVersionIndex = 0;
var checkingVersion = updatesOrderes.ElementAtOrDefault(checkingVersionIndex);
while (checkingVersion is not null && checkingVersion.Version > result.CurrentVersion)
{
var actionsToAdd = new List<UpdateAction>();
foreach (var action in checkingVersion.Actions)
{
if (!result.Actions.Any(n => n.DestPath == action.DestPath))
actionsToAdd.Add(action);
}
result.Actions.InsertRange(0, actionsToAdd);
checkingVersionIndex += 1;
checkingVersion = updatesOrderes.ElementAtOrDefault(checkingVersionIndex);
}
}
else
result.HasError = true;
}
if (!result.IsInstalled)
{
var infos = await DownloadInstallInfos();
if (infos is not null && infos.Actions.Count != 0)
result.Actions.AddRange(infos.Actions);
else
result.HasError = true;
}
return result;
}
public async Task<bool?> Install(UpdateCheckResult checkResult)
{
ModpackInfo modpackInfo;
int processed = 0;
var localZipCache = new List<LocalZipCacheEntry>();
if (ModpackInfo.HasModpackInfo(localPath))
modpackInfo = ModpackInfo.Load(localPath);
else
{
modpackInfo = new ModpackInfo();
}
foreach (InstallAction iaction in checkResult.Actions)
{
string destFilePath = Path.Combine(localPath, iaction.DestPath);
if (iaction is UpdateAction)
{
UpdateAction uaction = (UpdateAction)iaction;
switch (uaction.Type)
{
case UpdateActionType.Update:
await InstallFile(destFilePath, uaction.DownloadUrl, uaction.IsZip, uaction.ZipPath, localZipCache);
break;
case UpdateActionType.Delete:
{
if (uaction.IsDirectory)
{
if (Directory.Exists(destFilePath))
Directory.Delete(destFilePath, true);
}
else if (File.Exists(destFilePath))
File.Delete(destFilePath);
}
break;
case UpdateActionType.Copy:
{
var srcFilePath = Path.Combine(localPath, uaction.SrcPath);
if (uaction.IsDirectory)
{
if (Directory.Exists(srcFilePath))
Extensions.CopyDirectory(srcFilePath, destFilePath, true);
}
else if (File.Exists(srcFilePath))
{
Directory.CreateDirectory(Path.GetDirectoryName(destFilePath));
File.Copy(srcFilePath, destFilePath, true);
}
}
break;
case UpdateActionType.Move:
{
var srcFilePath = Path.Combine(localPath, uaction.SrcPath);
if (uaction.IsDirectory)
{
if (Directory.Exists(srcFilePath))
Directory.Move(srcFilePath, destFilePath);
}
else if (File.Exists(srcFilePath))
{
Directory.CreateDirectory(Path.GetDirectoryName(destFilePath));
File.Move(srcFilePath, destFilePath, true);
}
}
break;
}
}
else
await InstallFile(destFilePath, iaction.DownloadUrl, iaction.IsZip, iaction.ZipPath, localZipCache);
processed += 1;
InstallProgessUpdated?.Invoke(checkResult, processed);
}
// Save new modpack info
modpackInfo.Version = checkResult.LatestVersion;
modpackInfo.Save(localPath);
// Delete cached zip files
foreach (var task in localZipCache)
Directory.Delete(task.ExtractedZipPath, true);
return true;
}
private async Task InstallFile(string destFilePath, string sourceUrl, bool isZip, string zipPath, List<LocalZipCacheEntry> localZipCache)
{
Directory.CreateDirectory(Path.GetDirectoryName(destFilePath));
// Download
var fsDestinationPath = isZip ? Path.Combine(Path.GetTempPath(), $"mc_update_file_{DateTime.Now.ToBinary()}.zip") : destFilePath;
var sRemote = await httpClient.GetStreamAsync(sourceUrl);
var fs = new FileStream(destFilePath, FileMode.Create, FileAccess.ReadWrite);
await sRemote.CopyToAsync(fs);
sRemote.Close();
fs.Close();
// Handle zip file
if (isZip)
{
// Extract
var zipDir = $"{Path.GetFileNameWithoutExtension(fsDestinationPath)}_extracted";
ZipFile.ExtractToDirectory(fsDestinationPath, zipDir);
// Copy content
var zipSrc = Path.Combine(zipDir, zipPath);
Extensions.CopyDirectory(zipSrc, destFilePath, true);
// Delete/cache temporary files
File.Delete(fsDestinationPath);
localZipCache?.Add(new LocalZipCacheEntry
{
DownloadUrl = sourceUrl,
ExtractedZipPath = zipDir
});
}
}
}

View File

@@ -1,194 +0,0 @@
Imports System.IO
Imports System.IO.Compression
Imports System.Net.Http
Imports ModpackUpdater.Model
Public Class ModpackInstaller
Private Class LocalZipCacheEntry
Public Property DownloadUrl As String
Public Property ExtractedZipPath As String
End Class
Public Event InstallProgessUpdated(result As UpdateCheckResult, processedSyncs As Integer)
Public Event CheckingProgressUpdated(toCheck As Integer, processed As Integer)
Private ReadOnly updateConfig As ModpackConfig
Private ReadOnly localPath As String
Private httpClient As New HttpClient
Public Sub New(updateConfig As ModpackConfig, localPath As String)
Me.updateConfig = updateConfig
Me.localPath = localPath
End Sub
Protected Overrides Sub Finalize()
httpClient.Dispose()
MyBase.Finalize()
End Sub
Private Async Function DownloadUpdateInfos() As Task(Of UpdateInfos)
Dim content As String = Await httpClient.GetStringAsync(updateConfig.UpdateUrl)
Return UpdateInfos.Parse(content)
End Function
Private Async Function DownloadInstallInfos() As Task(Of InstallInfos)
Dim content As String = Await httpClient.GetStringAsync(updateConfig.InstallUrl)
Return InstallInfos.Parse(content)
End Function
Public Async Function Check(ignoreRevmoedFiles As Boolean) As Task(Of UpdateCheckResult)
Dim result As New UpdateCheckResult
If ModpackInfo.HasModpackInfo(localPath) Then
Dim infos As UpdateInfos = Await DownloadUpdateInfos()
Dim modpackInfo As ModpackInfo = ModpackInfo.Load(localPath)
If infos IsNot Nothing AndAlso infos.Updates.Count <> 0 Then
Dim updatesOrderes = infos.Updates.OrderByDescending(Function(n) n.Version)
result.LatestVersion = updatesOrderes.First.Version
result.CurrentVersion = modpackInfo.Version
result.IsInstalled = True
Dim checkingVersionIndex As Integer = 0
Dim checkingVersion As UpdateInfo = updatesOrderes(checkingVersionIndex)
Do While checkingVersion IsNot Nothing AndAlso checkingVersion.Version > result.CurrentVersion
Dim actionsToAdd As New List(Of UpdateAction)
For Each action In checkingVersion.Actions
If Not result.Actions.Any(Function(n) n.DestPath = action.DestPath) Then
actionsToAdd.Add(action)
End If
Next
result.Actions.InsertRange(0, actionsToAdd)
checkingVersionIndex += 1
checkingVersion = updatesOrderes.ElementAtOrDefault(checkingVersionIndex)
Loop
Else
result.HasError = True
End If
End If
If Not result.IsInstalled Then
Dim infos As InstallInfos = Await DownloadInstallInfos()
If infos IsNot Nothing AndAlso infos.Actions.Count <> 0 Then
result.Actions.AddRange(infos.Actions)
Else
result.HasError = True
End If
End If
Return result
End Function
Public Async Function Install(checkResult As UpdateCheckResult) As Task(Of Boolean?)
Dim modpackInfo As ModpackInfo
Dim processed As Integer = 0
Dim localZipCache As New List(Of LocalZipCacheEntry)
If ModpackInfo.HasModpackInfo(localPath) Then
modpackInfo = ModpackInfo.Load(localPath)
Else
modpackInfo = New ModpackInfo
End If
For Each iaction As InstallAction In checkResult.Actions
Dim destFilePath As String = Path.Combine(localPath, iaction.DestPath)
If TypeOf iaction Is UpdateAction Then
Dim uaction As UpdateAction = iaction
Select Case uaction.Type
Case UpdateActionType.Update
Await InstallFile(destFilePath, uaction.DownloadUrl, uaction.IsZip, uaction.ZipPath, localZipCache)
Case UpdateActionType.Delete
If uaction.IsDirectory Then
If Directory.Exists(destFilePath) Then
Directory.Delete(destFilePath, True)
End If
Else
If File.Exists(destFilePath) Then
File.Delete(destFilePath)
End If
End If
Case UpdateActionType.Copy
Dim srcFilePath As String = Path.Combine(localPath, uaction.SrcPath)
If uaction.IsDirectory Then
If Directory.Exists(srcFilePath) Then
CopyDirectory(srcFilePath, destFilePath, True)
End If
Else
If File.Exists(srcFilePath) Then
Directory.CreateDirectory(Path.GetDirectoryName(destFilePath))
File.Copy(srcFilePath, destFilePath, True)
End If
End If
Case UpdateActionType.Move
Dim srcFilePath As String = Path.Combine(localPath, uaction.SrcPath)
If uaction.IsDirectory Then
If Directory.Exists(srcFilePath) Then
Directory.Move(srcFilePath, destFilePath)
End If
Else
If File.Exists(srcFilePath) Then
Directory.CreateDirectory(Path.GetDirectoryName(destFilePath))
File.Move(srcFilePath, destFilePath, True)
End If
End If
End Select
Else
Await InstallFile(destFilePath, iaction.DownloadUrl, iaction.IsZip, iaction.ZipPath, localZipCache)
End If
processed += 1
RaiseEvent InstallProgessUpdated(checkResult, processed)
Next
'Save new modpack info
modpackInfo.Version = checkResult.LatestVersion
modpackInfo.Save(localPath)
'Delete cached zip files
For Each task In localZipCache
Directory.Delete(task.ExtractedZipPath, True)
Next
Return True
End Function
Private Async Function InstallFile(destFilePath As String, sourceUrl As String, isZip As Boolean, zipPath As String, localZipCache As List(Of LocalZipCacheEntry)) As Task
Directory.CreateDirectory(Path.GetDirectoryName(destFilePath))
'Download
Dim fsDestinationPath As String = If(isZip, Path.Combine(Path.GetTempPath(), $"mc_update_file_{Date.Now.ToBinary}.zip"), destFilePath)
Dim sRemote As Stream = Await httpClient.GetStreamAsync(sourceUrl)
Dim fs As New FileStream(destFilePath, FileMode.Create, FileAccess.ReadWrite)
Await sRemote.CopyToAsync(fs)
sRemote.Close()
fs.Close()
'Handle zip file
If isZip Then
'Extract
Dim zipDir As String = $"{Path.GetFileNameWithoutExtension(fsDestinationPath)}_extracted"
ZipFile.ExtractToDirectory(fsDestinationPath, zipDir)
'Copy content
Dim zipSrc As String = Path.Combine(zipDir, zipPath)
CopyDirectory(zipSrc, destFilePath, True)
'Delete/cache temporary files
File.Delete(fsDestinationPath)
localZipCache?.Add(New LocalZipCacheEntry With {
.DownloadUrl = sourceUrl,
.ExtractedZipPath = zipDir
})
End If
End Function
End Class

View File

@@ -1,16 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>ModpackUpdater.Manager</RootNamespace>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ModpackUpdater.Model\ModpackUpdater.Model.vbproj" />
<ProjectReference Include="..\ModpackUpdater.Model\ModpackUpdater.Model.csproj" />
</ItemGroup>
</Project>
</Project>

View File

@@ -0,0 +1,13 @@
using ModpackUpdater.Model;
namespace ModpackUpdater.Manager;
public class UpdateCheckResult
{
public Version CurrentVersion { get; set; }
public Version LatestVersion { get; set; }
public List<InstallAction> Actions { get; private set; } = [];
public bool IsInstalled { get; set; }
public bool HasError { get; set; }
public bool HasUpdates => !IsInstalled || CurrentVersion < LatestVersion;
}

View File

@@ -1,17 +0,0 @@
Imports ModpackUpdater.Model
Public Class UpdateCheckResult
Public Property CurrentVersion As Version
Public Property LatestVersion As Version
Public ReadOnly Property Actions As New List(Of InstallAction)
Public Property IsInstalled As Boolean
Public Property HasError As Boolean
Public ReadOnly Property HasUpdates As Boolean
Get
Return Not IsInstalled OrElse CurrentVersion < LatestVersion
End Get
End Property
End Class