Files
minecraft-modpack-updater/ModpackUpdater/UpdateInstaller.vb
2022-06-14 12:15:29 +02:00

154 lines
5.8 KiB
VB.net

Imports System.IO
Imports System.Net
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 UpdateConfig
Private ReadOnly localPath As String
Private webdavClient As WebDavClient = Nothing
Public Sub New(updateConfig As UpdateConfig, localPath As String)
Me.updateConfig = updateConfig
Me.localPath = localPath
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
Public Async Function CheckForUpdates(ignoreRevmoedFiles As Boolean) As Task(Of UpdateCheckResult)
Dim result As New UpdateCheckResult
Dim client As WebDavClient = CreateClient()
Dim resTopFolder As WebDavResource = Nothing
Dim checkedFiles = New List(Of String)()
Dim responseSuccessfull As Boolean = False
'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
Return result
End Function
Public Async Function InstallUpdates(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