diff --git a/ModpackUpdater.Manager/ModpackInstaller.vb b/ModpackUpdater.Manager/ModpackInstaller.vb new file mode 100644 index 0000000..1c3728c --- /dev/null +++ b/ModpackUpdater.Manager/ModpackInstaller.vb @@ -0,0 +1,121 @@ +Imports System.IO +Imports System.Net +Imports System.Net.Http + +Imports ModpackUpdater.Model + +Public Class ModpackInstaller + + 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 + + Public Async Function CheckForUpdates(ignoreRevmoedFiles As Boolean) As Task(Of UpdateCheckResult) + Dim infos As UpdateInfos = Await DownloadUpdateInfos() + Dim result As New UpdateCheckResult + + If infos IsNot Nothing AndAlso infos.Updates.Any Then + Dim updatesOrderes = infos.Updates.OrderByDescending(Function(n) n.Version) + result.LatestVersion = updatesOrderes.First.Version + + If ModpackInfo.HasModpackInfo(localPath) Then + Dim modpackInfo As ModpackInfo = ModpackInfo.Load(localPath) + result.CurrentVersion = modpackInfo.Version + + 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.UpdateActions.Any(Function(n) n.DestPath = action.DestPath) Then + actionsToAdd.Add(action) + End If + Next + + result.UpdateActions.InsertRange(0, actionsToAdd) + + checkingVersionIndex += 1 + checkingVersion = updatesOrderes.ElementAtOrDefault(checkingVersionIndex) + Loop + End If + End If + + Return result + End Function + + Public Async Function InstallUpdates(checkResult As UpdateCheckResult) As Task(Of Boolean?) + Dim modpackInfo As ModpackInfo + + If ModpackInfo.HasModpackInfo(localPath) Then + modpackInfo = ModpackInfo.Load(localPath) + Else + modpackInfo = New ModpackInfo + End If + + Dim processed As Integer = 0 + For Each action As UpdateAction In checkResult.UpdateActions + Dim destFilePath As String = Path.Combine(localPath, action.DestPath) + + Select Case action.Type + Case UpdateActionType.Update + Directory.CreateDirectory(Path.GetDirectoryName(destFilePath)) + Dim sRemote As Stream = Await httpClient.GetStreamAsync(action.DownloadUrl) + Dim fs As New FileStream(destFilePath, FileMode.Create, FileAccess.ReadWrite) + Await sRemote.CopyToAsync(fs) + sRemote.Close() + fs.Close() + Case UpdateActionType.Delete + If action.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, action.SrcPath) + If File.Exists(srcFilePath) Then + Directory.CreateDirectory(Path.GetDirectoryName(destFilePath)) + File.Copy(srcFilePath, destFilePath, True) + End If + Case UpdateActionType.Move + Dim srcFilePath As String = Path.Combine(localPath, action.SrcPath) + If File.Exists(srcFilePath) Then + Directory.CreateDirectory(Path.GetDirectoryName(destFilePath)) + File.Move(srcFilePath, destFilePath, True) + End If + End Select + + processed += 1 + RaiseEvent InstallProgessUpdated(checkResult, processed) + Next + + modpackInfo.Version = checkResult.LatestVersion + modpackInfo.Save(localPath) + + Return True + End Function + +End Class diff --git a/ModpackUpdater.Manager/ModpackUpdater.Manager.vbproj b/ModpackUpdater.Manager/ModpackUpdater.Manager.vbproj index a5b3134..a69543d 100644 --- a/ModpackUpdater.Manager/ModpackUpdater.Manager.vbproj +++ b/ModpackUpdater.Manager/ModpackUpdater.Manager.vbproj @@ -5,10 +5,6 @@ net8.0 - - - - diff --git a/ModpackUpdater.Manager/UpdateCheckResult.vb b/ModpackUpdater.Manager/UpdateCheckResult.vb index d73f424..ae15c4d 100644 --- a/ModpackUpdater.Manager/UpdateCheckResult.vb +++ b/ModpackUpdater.Manager/UpdateCheckResult.vb @@ -2,9 +2,6 @@ Public Class UpdateCheckResult - Public Property IsLegacy As Boolean - Public ReadOnly Property SyncFiles As New List(Of UpdateSyncFile) - Public Property CurrentVersion As Version Public Property LatestVersion As Version Public ReadOnly Property UpdateActions As New List(Of UpdateAction) @@ -12,11 +9,7 @@ Public Class UpdateCheckResult Public ReadOnly Property HasUpdates As Boolean Get - If IsLegacy Then - Return SyncFiles.Where(Function(n) n.SyncAction <> UpdateSyncAction.None).Any - Else - Return CurrentVersion < LatestVersion - End If + Return CurrentVersion < LatestVersion End Get End Property diff --git a/ModpackUpdater.Manager/UpdateInstaller.vb b/ModpackUpdater.Manager/UpdateInstaller.vb deleted file mode 100644 index cc12d5f..0000000 --- a/ModpackUpdater.Manager/UpdateInstaller.vb +++ /dev/null @@ -1,268 +0,0 @@ -Imports System.IO -Imports System.Net -Imports System.Net.Http - -Imports ModpackUpdater.Model - -Imports WebDav - -Public Class UpdateInstaller - - 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 webdavClient As WebDavClient = Nothing - 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 Function CreateClient() As WebDavClient - If webdavClient Is Nothing Then - Dim params As New WebDavClientParams With { - .BaseAddress = New Uri(updateConfig.WebdavURL), - .Credentials = New NetworkCredential(updateConfig.WebdavUsername, updateConfig.WebdavPassword) - } - webdavClient = New WebDavClient(params) - End If - - Return webdavClient - End Function - - Private Async Function DownloadUpdateInfos() As Task(Of UpdateInfos) - Dim content As String = Await httpClient.GetStringAsync(updateConfig.UpdateUrl) - Return UpdateInfos.Parse(content) - End Function - - Public Async Function CheckForUpdates(ignoreRevmoedFiles As Boolean) As Task(Of UpdateCheckResult) - Dim infos As UpdateInfos = Await DownloadUpdateInfos() - Dim result As New UpdateCheckResult - - If infos IsNot Nothing AndAlso infos.Updates.Any Then - Dim updatesOrderes = infos.Updates.OrderByDescending(Function(n) n.Version) - result.LatestVersion = updatesOrderes.First.Version - - If ModpackInfo.HasModpackInfo(localPath) Then - Dim modpackInfo As ModpackInfo = ModpackInfo.Load(localPath) - result.CurrentVersion = modpackInfo.Version - - 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.UpdateActions.Any(Function(n) n.DestPath = action.DestPath) Then - actionsToAdd.Add(action) - End If - Next - - result.UpdateActions.InsertRange(0, actionsToAdd) - - checkingVersionIndex += 1 - checkingVersion = updatesOrderes.ElementAtOrDefault(checkingVersionIndex) - Loop - Else - Await CheckForUpdatesLegacy(result, ignoreRevmoedFiles) - End If - End If - - Return result - End Function - - Private Async Function CheckForUpdatesLegacy(result As UpdateCheckResult, ignoreRevmoedFiles As Boolean) As Task - Dim client As WebDavClient = CreateClient() - Dim resTopFolder As WebDavResource = Nothing - Dim checkedFiles = New List(Of String)() - Dim responseSuccessfull As Boolean = False - - result.CurrentVersion = New Version("0.0.0.0") - result.IsLegacy = True - - 'Check for new & updated files - Dim response = Await client.Propfind(String.Empty, New PropfindParameters() With {.ApplyTo = ApplyTo.Propfind.ResourceAndAncestors}) - If resTopFolder Is Nothing AndAlso response.IsSuccessful AndAlso response.Resources.Any() Then - resTopFolder = response.Resources.ElementAtOrDefault(0) - responseSuccessfull = True - End If - - If responseSuccessfull AndAlso response.Resources.Count > 1 Then - Dim i As Integer = 1 - Dim loopTo As Integer = response.Resources.Count - 1 - - Do While i <= loopTo - Dim res = response.Resources.ElementAtOrDefault(i) - Dim isFolder As Boolean = res.Uri.EndsWith("/") - - If Not isFolder Then - Dim syncAction? As UpdateSyncAction = Nothing - Dim localFile As String - Dim remoteFile As String - - 'Get remote file path - remoteFile = res.Uri - - 'Get local file path - localFile = Path.Combine(localPath, Uri.UnescapeDataString(res.Uri.Substring(resTopFolder.Uri.Length)).Replace("/", "\")) - - 'Check action - If File.Exists(localFile) Then - If File.GetLastWriteTime(localFile) < res.LastModifiedDate = True Then - syncAction = UpdateSyncAction.UpdatedFile - End If - Else - syncAction = UpdateSyncAction.NewFile - End If - - 'Add to list - checkedFiles.Add(localFile) - If syncAction IsNot Nothing Then - result.SyncFiles.Add(New UpdateSyncFile(syncAction, localFile, remoteFile)) - End If - End If - - i += 1 - - RaiseEvent CheckingProgressUpdated(loopTo, i) - Loop - End If - - 'Find all old files to remove - If responseSuccessfull Then - Dim allLocalFiles = Directory.GetFiles(localPath, "*", SearchOption.AllDirectories) - For Each lf As String In allLocalFiles - Dim isKnown As Boolean = False - - For Each checkedFile As String In checkedFiles - If Not isKnown AndAlso If(checkedFile, "") = If(lf, "") Then - isKnown = True - End If - Next - - If Not isKnown Then - result.SyncFiles.Add(New UpdateSyncFile(If(ignoreRevmoedFiles, UpdateSyncAction.None, UpdateSyncAction.RemovedFile), lf, String.Empty)) - End If - Next - End If - End Function - - Public Async Function InstallUpdates(checkResult As UpdateCheckResult, Optional ignoreActions As UpdateSyncAction = UpdateSyncAction.None) As Task(Of Boolean?) - Dim isSuccessfully As Boolean - Dim modpackInfo As ModpackInfo - - If ModpackInfo.HasModpackInfo(localPath) Then - modpackInfo = ModpackInfo.Load(localPath) - Else - modpackInfo = New ModpackInfo - End If - - If checkResult.IsLegacy Then - isSuccessfully = Await InstallUpdatesLegacy(checkResult, ignoreActions) - Else - Dim processed As Integer = 0 - For Each action As UpdateAction In checkResult.UpdateActions - Dim destFilePath As String = Path.Combine(localPath, action.DestPath) - - Select Case action.Type - Case UpdateActionType.Update - Directory.CreateDirectory(Path.GetDirectoryName(destFilePath)) - Dim sRemote As Stream = Await httpClient.GetStreamAsync(action.DownloadUrl) - Dim fs As New FileStream(destFilePath, FileMode.Create, FileAccess.ReadWrite) - Await sRemote.CopyToAsync(fs) - sRemote.Close() - fs.Close() - Case UpdateActionType.Delete - If action.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, action.SrcPath) - If File.Exists(srcFilePath) Then - Directory.CreateDirectory(Path.GetDirectoryName(destFilePath)) - File.Copy(srcFilePath, destFilePath, True) - End If - Case UpdateActionType.Move - Dim srcFilePath As String = Path.Combine(localPath, action.SrcPath) - If File.Exists(srcFilePath) Then - Directory.CreateDirectory(Path.GetDirectoryName(destFilePath)) - File.Move(srcFilePath, destFilePath, True) - End If - End Select - - processed += 1 - RaiseEvent InstallProgessUpdated(checkResult, processed) - Next - - isSuccessfully = True - End If - - If isSuccessfully Then - modpackInfo.Version = checkResult.LatestVersion - modpackInfo.Save(localPath) - End If - - Return isSuccessfully - End Function - - Private Async Function InstallUpdatesLegacy(checkResult As UpdateCheckResult, Optional ignoreActions As UpdateSyncAction = UpdateSyncAction.None) As Task(Of Boolean?) - Dim client As WebDavClient = CreateClient() - Dim success As Boolean? = False - Dim processed As Integer = 0 - - 'Init process update - RaiseEvent InstallProgessUpdated(checkResult, processed) - - For Each syncFile In checkResult.SyncFiles - If syncFile.SyncAction <> (ignoreActions And syncFile.SyncAction) Then - If syncFile.SyncAction = UpdateSyncAction.UpdatedFile OrElse - syncFile.SyncAction = UpdateSyncAction.RemovedFile Then - - If File.Exists(syncFile.LocalFile) Then - File.Delete(syncFile.LocalFile) - End If - End If - - If syncFile.SyncAction = UpdateSyncAction.UpdatedFile OrElse - syncFile.SyncAction = UpdateSyncAction.NewFile Then - - Dim response = Await client.GetProcessedFile(syncFile.RemoveFile) - Dim dirParent As New DirectoryInfo(Path.GetDirectoryName(syncFile.LocalFile)) - - If response.IsSuccessful Then - If Not dirParent.Exists Then - dirParent.Create() - End If - - Dim fs As New FileStream(syncFile.LocalFile, FileMode.Create, FileAccess.Write) - response.Stream.CopyTo(fs) - fs.Close() - - success = True - End If - End If - End If - - processed += 1 - RaiseEvent InstallProgessUpdated(checkResult, processed) - Next - - Return success - End Function - -End Class diff --git a/ModpackUpdater.Manager/UpdateSyncAction.vb b/ModpackUpdater.Manager/UpdateSyncAction.vb deleted file mode 100644 index ec6f578..0000000 --- a/ModpackUpdater.Manager/UpdateSyncAction.vb +++ /dev/null @@ -1,11 +0,0 @@ -Imports Newtonsoft.Json -Imports Newtonsoft.Json.Converters - - - -Public Enum UpdateSyncAction - None - NewFile - RemovedFile - UpdatedFile = 4 -End Enum diff --git a/ModpackUpdater.Manager/UpdateSyncFile.vb b/ModpackUpdater.Manager/UpdateSyncFile.vb deleted file mode 100644 index 669539a..0000000 --- a/ModpackUpdater.Manager/UpdateSyncFile.vb +++ /dev/null @@ -1,13 +0,0 @@ -Public Class UpdateSyncFile - - Public ReadOnly Property SyncAction As UpdateSyncAction - Public ReadOnly Property LocalFile As string - Public ReadOnly Property RemoveFile As string - - Public Sub New(syncAction As UpdateSyncAction, localFile As string, remoteFile As string) - Me.SyncAction = syncAction - Me.LocalFile = localFile - Me.RemoveFile = remoteFile - End Sub - -End Class diff --git a/ModpackUpdater/Form1.vb b/ModpackUpdater/Form1.vb index 5625789..97eb809 100644 --- a/ModpackUpdater/Form1.vb +++ b/ModpackUpdater/Form1.vb @@ -88,7 +88,7 @@ Public Class Form1 End Sub Private Async Function ExecuteUpdate(doInstall As Boolean) As Task - Dim updater As New UpdateInstaller(updateConfig, GetMinecraftProfilePath) + Dim updater As New ModpackInstaller(updateConfig, GetMinecraftProfilePath) AddHandler updater.InstallProgessUpdated, AddressOf Update_InstallProgessUpdated AddHandler updater.CheckingProgressUpdated, AddressOf Updated_CheckingProgresssUpdated @@ -132,7 +132,7 @@ Public Class Form1 End Function Private Sub Update_InstallProgessUpdated(result As UpdateCheckResult, processedSyncs As Integer) - Dim actionCount = If(result.IsLegacy, result.SyncFiles.Count, result.UpdateActions.Count) + Dim actionCount = result.UpdateActions.Count SetStatus(Math.Round(processedSyncs / actionCount * 100, 1) & "%", MySymbols.icons8_software_installer_16px) End Sub