Files
minecraft-modpack-updater/ModpackUpdater.Manager/ModpackInstaller.vb

161 lines
6.4 KiB
VB.net

Imports System.IO
Imports System.IO.Compression
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
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
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)
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 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, uaction.SrcPath)
If File.Exists(srcFilePath) Then
Directory.CreateDirectory(Path.GetDirectoryName(destFilePath))
File.Move(srcFilePath, destFilePath, True)
End If
End Select
Else
Await InstallFile(destFilePath, iaction.DownloadUrl, iaction.IsZip, iaction.ZipPath)
End If
processed += 1
RaiseEvent InstallProgessUpdated(checkResult, processed)
Next
modpackInfo.Version = checkResult.LatestVersion
modpackInfo.Save(localPath)
Return True
End Function
Private Async Function InstallFile(destFilePath As String, sourceUrl As String, isZip As Boolean, zipPath As String) As Task
Directory.CreateDirectory(Path.GetDirectoryName(destFilePath))
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()
If isZip Then
Dim zipDir As String = $"{Path.GetFileNameWithoutExtension(fsDestinationPath)}_extracted"
ZipFile.ExtractToDirectory(fsDestinationPath, zipDir)
'...
File.Delete(fsDestinationPath)
Directory.Delete(zipDir, True)
End If
End Function
End Class