mirror of
https://github.com/AAndyProgram/SCrawler.git
synced 2026-03-14 15:52:18 +00:00
2023.12.6.0
Add updater
This commit is contained in:
248
SCrawler.Updater/MainMod.vb
Normal file
248
SCrawler.Updater/MainMod.vb
Normal file
@@ -0,0 +1,248 @@
|
||||
' Copyright (C) Andy https://github.com/AAndyProgram
|
||||
' This program is free software: you can redistribute it and/or modify
|
||||
' it under the terms of the GNU General Public License as published by
|
||||
' the Free Software Foundation, either version 3 of the License, or
|
||||
' (at your option) any later version.
|
||||
'
|
||||
' This program is distributed in the hope that it will be useful,
|
||||
' but WITHOUT ANY WARRANTY
|
||||
Imports System.Net
|
||||
Imports System.IO.Compression
|
||||
Imports PersonalUtilities.Functions
|
||||
Imports PersonalUtilities.Functions.XML
|
||||
Imports PersonalUtilities.Tools.Web.Clients
|
||||
Imports PersonalUtilities.Tools.Web.Documents.JSON
|
||||
Public Module MainMod
|
||||
Private Const NewReleaseFolderName As String = "__NewRelease"
|
||||
Private MyProcessID As Integer = -1
|
||||
Private MyWorkingPath As SFile = Nothing
|
||||
Private ReadOnly ProcessNames As String() = {"SCrawler", "YouTubeDownloader", "Updater"}
|
||||
Private Silent As Boolean = False
|
||||
Private Function GetConsoleResponse(ByVal Request As String) As String
|
||||
Console.Write(Request)
|
||||
Return Console.ReadLine
|
||||
End Function
|
||||
Private Function DownloadFile(ByVal URL As String, ByVal Destination As SFile) As Boolean
|
||||
Try
|
||||
Dim lastPerc% = -1
|
||||
Dim currentCursor% = Console.CursorTop
|
||||
Using w As New RWebClient With {.AsyncMode = True}
|
||||
AddHandler w.DownloadProgressChanged,
|
||||
New DownloadProgressChangedEventHandler(Sub(ByVal Sender As Object, ByVal e As DownloadProgressChangedEventArgs)
|
||||
If lastPerc < e.ProgressPercentage Then
|
||||
lastPerc = e.ProgressPercentage
|
||||
Console.SetCursorPosition(0, currentCursor)
|
||||
Console.Write("{0}% completed", e.ProgressPercentage)
|
||||
End If
|
||||
End Sub)
|
||||
Return w.DownloadFile(URL, Destination, EDP.ReturnValue)
|
||||
End Using
|
||||
Catch ex As Exception
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
Public Sub Main()
|
||||
Try
|
||||
MyWorkingPath = AppDomain.CurrentDomain.BaseDirectory.CSFileP
|
||||
MyProcessID = Process.GetCurrentProcess.Id
|
||||
Console.Title = "SCrawler updater"
|
||||
With Environment.GetCommandLineArgs
|
||||
If .ListExists(2) Then Silent = .Self()(1).FromXML(Of Boolean)(False)
|
||||
End With
|
||||
|
||||
Dim currentDir As SFile = MyWorkingPath.CutPath
|
||||
Dim extractionDir As SFile = $"{currentDir.CSFilePS}{NewReleaseFolderName}\"
|
||||
If extractionDir.Exists(SFO.Path, False) Then extractionDir.Delete(SFO.Path, SFODelete.DeletePermanently, EDP.None)
|
||||
|
||||
Dim currVer As Version = GetCurrentMaxVer(currentDir)
|
||||
If currVer Is Nothing Then
|
||||
Console.WriteLine("The current version of the program cannot be determined")
|
||||
Else
|
||||
Console.WriteLine($"The current version is {currVer} (x{IIf(Environment.Is64BitProcess, 64, 86)})")
|
||||
Dim release As GitRelease = GetGitRelease()
|
||||
If Not release.URL.IsEmptyString And Not release.Version Is Nothing Then
|
||||
If release.Version > currVer Then
|
||||
Console.WriteLine($"The new version is {release.Version} ({release.Name})")
|
||||
|
||||
If Not Silent AndAlso GetConsoleResponse("Do you want to update the program? (y/n): ").IfNullOrEmpty("n") = "n" Then Exit Sub
|
||||
|
||||
If ActiveProcessesExist() Then
|
||||
Console.WriteLine("One of the SCrawler programs is still running. Waiting for all SCrawler programs to close.")
|
||||
While ActiveProcessesExist() : Threading.Thread.Sleep(100) : End While
|
||||
Console.WriteLine("All SCrawler programs are closed.")
|
||||
End If
|
||||
|
||||
If extractionDir.Exists(SFO.Path, True) Then
|
||||
Dim destFile As SFile = $"{extractionDir.CSFilePS}{New SFile(release.URL).File}"
|
||||
Console.WriteLine("Downloading new version...")
|
||||
If DownloadFile(release.URL, destFile) Then
|
||||
Console.WriteLine("")
|
||||
Console.WriteLine("New version downloaded!")
|
||||
Console.WriteLine("Extracting files...")
|
||||
ZipFile.ExtractToDirectory(destFile, extractionDir)
|
||||
Console.WriteLine("Files extracted!")
|
||||
destFile.Delete(SFO.File, SFODelete.DeletePermanently, EDP.None)
|
||||
If Not MoveFiles(extractionDir, currentDir) Then GetConsoleResponse("Unable to update the program. Press Enter to exit") : Exit Sub
|
||||
Else
|
||||
extractionDir.Delete(SFO.Path, SFODelete.DeletePermanently, EDP.None)
|
||||
Console.WriteLine("Unable to download new version")
|
||||
End If
|
||||
Else
|
||||
Console.WriteLine("Unable to create temp directory")
|
||||
End If
|
||||
Else
|
||||
Console.WriteLine("The program is up to date")
|
||||
End If
|
||||
Else
|
||||
Console.WriteLine("Unable to get information about new version")
|
||||
End If
|
||||
End If
|
||||
Catch ex As Exception
|
||||
Console.WriteLine("An error occurred during update")
|
||||
Console.WriteLine(ex.Message)
|
||||
Finally
|
||||
GetConsoleResponse("Press Enter to exit")
|
||||
End Try
|
||||
End Sub
|
||||
Private Function MoveFiles(ByVal Source As SFile, ByVal Destination As SFile) As Boolean
|
||||
Console.WriteLine("Updating files")
|
||||
Try
|
||||
|
||||
Dim oldFiles As List(Of SFile) = SFile.GetFiles(Destination,,, EDP.ReturnValue)
|
||||
Dim oldFolders As List(Of SFile) = SFile.GetDirectories(Destination,,, EDP.ReturnValue)
|
||||
|
||||
Dim newFiles As List(Of SFile) = SFile.GetFiles(Source,,, EDP.ReturnValue)
|
||||
Dim newFolders As List(Of SFile) = SFile.GetDirectories(Source,,, EDP.ReturnValue)
|
||||
|
||||
Dim obj As SFile = Nothing
|
||||
Dim wSegment As String = MyWorkingPath.Segments.Last
|
||||
Dim filesPredicate As Predicate(Of SFile) = Function(ByVal f As SFile) As Boolean
|
||||
If obj = f Or obj.Name = f.Name Then
|
||||
f.Delete(SFO.File, SFODelete.DeleteToRecycleBin, EDP.None)
|
||||
Return True
|
||||
Else
|
||||
Return False
|
||||
End If
|
||||
End Function
|
||||
Dim foldersPredicate As Predicate(Of SFile) = Function(ByVal f As SFile) As Boolean
|
||||
Dim ls$ = f.Segments.Last
|
||||
If ls = obj.Segments.Last And Not ls = NewReleaseFolderName And Not ls = wSegment Then
|
||||
f.Delete(SFO.Path, SFODelete.DeleteToRecycleBin, EDP.None)
|
||||
Return True
|
||||
Else
|
||||
Return False
|
||||
End If
|
||||
End Function
|
||||
|
||||
Dim getDestFile As Func(Of SFile, Boolean, SFile) = Function(ByVal f As SFile, ByVal isFolder As Boolean) As SFile
|
||||
Dim ff As SFile = f
|
||||
If isFolder Then
|
||||
ff = $"{Destination.PathWithSeparator}{f.Segments.Last}\"
|
||||
Else
|
||||
ff.Path = Destination.Path
|
||||
End If
|
||||
Console.WriteLine(ff)
|
||||
Return ff
|
||||
End Function
|
||||
If newFiles.ListExists Then
|
||||
If oldFiles.ListExists Then
|
||||
For Each obj In newFiles : oldFiles.RemoveAll(filesPredicate) : Next
|
||||
End If
|
||||
newFiles.ForEach(Sub(ff) SFile.Move(ff, getDestFile(ff, False), SFO.File, True, SFODelete.DeleteToRecycleBin, EDP.None))
|
||||
End If
|
||||
|
||||
If newFolders.ListExists Then
|
||||
If oldFolders.ListExists Then
|
||||
For Each obj In newFolders : oldFolders.RemoveAll(foldersPredicate) : Next
|
||||
End If
|
||||
newFolders.ForEach(Sub(ff) If Not ff.Segments.Last = wSegment Then _
|
||||
SFile.Move(ff, getDestFile(ff, True), SFO.Path, True, SFODelete.DeleteToRecycleBin, EDP.None))
|
||||
End If
|
||||
|
||||
Console.WriteLine("Files updated")
|
||||
Return True
|
||||
Catch
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
Private Function ActiveProcessesExist() As Boolean
|
||||
Try
|
||||
Return Process.GetProcesses.Any(Function(p) ProcessNames.Contains(p.ProcessName) And Not p.Id = MyProcessID)
|
||||
Catch
|
||||
Return True
|
||||
End Try
|
||||
End Function
|
||||
Private Structure GitRelease
|
||||
Friend URL As String
|
||||
Friend Name As String
|
||||
Friend Version As Version
|
||||
End Structure
|
||||
Private Function GetGitRelease() As GitRelease
|
||||
Try
|
||||
Dim nameEnd$ = $"_x{IIf(Environment.Is64BitProcess, 64, 86)}.zip"
|
||||
Dim name$, relName$, relTag$
|
||||
|
||||
Using resp As New Responser With {.Accept = "application/vnd.github.v3+json"}
|
||||
Dim r$ = resp.GetResponse("https://api.github.com/repos/AAndyProgram/SCrawler/releases",, EDP.ReturnValue)
|
||||
If Not r.IsEmptyString Then
|
||||
Dim getver As Func(Of String, Version) = Function(ByVal input As String) As Version
|
||||
Try
|
||||
If Not input.IsEmptyString Then
|
||||
If input.ToLower.StartsWith("scrawler") Then
|
||||
Return New Version(input.Split("_")(1))
|
||||
Else
|
||||
Return New Version(input)
|
||||
End If
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
Using j As EContainer = JsonDocument.Parse(r, EDP.ReturnValue)
|
||||
If j.ListExists Then
|
||||
With j.FirstOrDefault(Function(e) Not e.Value("draft").FromXML(Of Boolean) And Not e.Value("prerelease").FromXML(Of Boolean))
|
||||
If .ListExists Then
|
||||
relName = .Value("name")
|
||||
relTag = .Value("tag_name")
|
||||
With .Item("assets")
|
||||
If .ListExists Then
|
||||
For Each asset As EContainer In .Self
|
||||
name = asset.Value("name")
|
||||
If Not name.IsEmptyString AndAlso name.EndsWith(nameEnd) Then _
|
||||
Return New GitRelease With {
|
||||
.Name = name,
|
||||
.URL = asset.Value("browser_download_url"),
|
||||
.Version = getver(name).IfNullOrEmpty(getver(relName).IfNullOrEmpty(getver(relTag)))}
|
||||
Next
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
End With
|
||||
End If
|
||||
End Using
|
||||
End If
|
||||
End Using
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
Private Function GetCurrentMaxVer(ByVal Path As SFile) As Version
|
||||
Try
|
||||
If Path.Exists(SFO.Path, False) Then
|
||||
Dim versions As New List(Of Version)
|
||||
Dim v As FileVersionInfo
|
||||
With SFile.GetFiles(Path, "*.exe",, EDP.ReturnValue).ListIfNothing.Where(Function(f) f.Name = "SCrawler" Or f.Name = "YouTubeDownloader")
|
||||
If .ListExists Then
|
||||
For Each f As SFile In .Self
|
||||
v = FileVersionInfo.GetVersionInfo(f)
|
||||
versions.Add(New Version(v.ProductVersion))
|
||||
Next
|
||||
End If
|
||||
End With
|
||||
If versions.Count > 0 Then Return versions.LastOrDefault
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
Return Nothing
|
||||
End Function
|
||||
End Module
|
||||
Reference in New Issue
Block a user