Added SelfUpdate

This commit is contained in:
2024-07-13 22:33:09 +03:00
parent 349c669284
commit 6599428043
8 changed files with 157 additions and 95 deletions

View File

@@ -5,15 +5,12 @@ namespace DiscordBotCore.Interfaces.Updater
{
public class AppVersion : IVersion
{
public int Major { get; set; }
public int Minor { get; set; }
public int Patch { get; set; }
public int PatchVersion { get; set; }
public static readonly AppVersion CurrentAppVersion = new AppVersion(Assembly.GetEntryAssembly().GetName().Version.ToString());
public int Major { get; set; }
public int Minor { get; set; }
public int Patch { get; set; }
public int PatchVersion { get; set; }
private readonly char _Separator = '.';

View File

@@ -150,7 +150,10 @@ public static class ArchiveManager
try
{
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
string path = Path.Combine(folder, entry.FullName);
Directory.CreateDirectory(Path.GetDirectoryName(path));
entry.ExtractToFile(path, true);
currentSize += (ulong)entry.CompressedLength;
}
catch (Exception ex)

View File

@@ -1,93 +1,126 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using DiscordBotCore.Interfaces.Updater;
using DiscordBotCore.Online;
using DiscordBotCore.Others;
namespace DiscordBotCore.Updater.Application
{
public class AppUpdater
{
private static readonly string _DefaultUpdateUrl = "https://github.com/andreitdr/SethDiscordBot/releases/latest";
const string ProjectName = "SethDiscordBot";
private static readonly string _DefaultUpdateUrl = $"https://github.com/andreitdr/{ProjectName}/releases/latest";
private static readonly string _DefaultUpdateDownloadUrl = $"https://github.com/andreitdr/{ProjectName}/releases/download/v";
private static readonly string _WindowsUpdateFile = "win-x64.zip";
private static readonly string _LinuxUpdateFile = "linux-x64.zip";
private static readonly string _MacOSUpdateFile = "osx-x64.zip";
private static readonly string _TempUpdateFolder = "temp";
private async Task<AppVersion> GetOnlineVersion()
{
HttpClient client = new HttpClient();
var response = await client.GetAsync(_DefaultUpdateUrl);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
var version = Regex.Match(content, @"<title>.+?v(\d+\.\d+\.\d+.\d+).+?</title>").Groups[1].Value;
return new AppVersion(version);
}
return AppVersion.CurrentAppVersion;
}
public async Task<Update> CheckForUpdates()
{
var latestVersion = await GetOnlineVersion();
if(latestVersion.IsNewerThan(AppVersion.CurrentAppVersion))
{
return new Update(AppVersion.CurrentAppVersion, latestVersion, _DefaultUpdateUrl, await GetUpdateNotes());
}
return Update.None;
}
private async Task<string> GetUpdateNotes()
{
HttpClient client = new HttpClient();
var response = await client.GetAsync(_DefaultUpdateUrl);
if (!response.IsSuccessStatusCode)
{
return string.Empty;
}
var content = await response.Content.ReadAsStringAsync();
var markdownStart = content.IndexOf("<div data-pjax=\"true\" data-test-selector=\"body-content\"");
if(markdownStart == -1)
{
return string.Empty;
}
markdownStart = content.IndexOf(">", markdownStart) + 1; // Move past the opening tag
var markdownEnd = content.IndexOf("</div>", markdownStart);
var markdown = content.Substring(markdownStart, markdownEnd - markdownStart).Trim();
markdown = RemoveHtmlTags(markdown);
markdown = ApplyMarkdownFormatting(markdown);
return markdown;
return AppVersion.CurrentAppVersion;
var url = response.RequestMessage.RequestUri.ToString();
var version = url.Split('/')[^1].Substring(1); // Remove the 'v' from the version number
return new AppVersion(version);
}
private string GetDownloadUrl(AppVersion version)
{
string downloadUrl = _DefaultUpdateDownloadUrl;
downloadUrl += $"{version.ToShortString()}/";
if(OperatingSystem.IsWindows())
downloadUrl += _WindowsUpdateFile;
else if (OperatingSystem.IsLinux())
downloadUrl += _LinuxUpdateFile;
else if (OperatingSystem.IsMacOS())
downloadUrl += _MacOSUpdateFile;
else
throw new PlatformNotSupportedException("Unsupported operating system");
return downloadUrl;
}
private string RemoveHtmlTags(string text)
public async Task<Update?> PrepareUpdate()
{
return Regex.Replace(text, "<.*?>", "").Trim();
AppVersion currentVersion = AppVersion.CurrentAppVersion;
AppVersion newVersion = await GetOnlineVersion();
if(!newVersion.IsNewerThan(currentVersion))
return null;
string downloadUrl = GetDownloadUrl(newVersion);
Update update = new Update(currentVersion, newVersion, downloadUrl);
return update;
}
private string ApplyMarkdownFormatting(string markdown)
private void PrepareCurrentFolderForOverwrite()
{
// Apply markdown formatting
markdown = markdown.Replace("**", "**"); // Bold
markdown = markdown.Replace("*", "*"); // Italic
markdown = markdown.Replace("`", "`"); // Inline code
markdown = markdown.Replace("```", "```"); // Code block
markdown = markdown.Replace("&gt;", ">"); // Greater than symbol
markdown = markdown.Replace("&lt;", "<"); // Less than symbol
markdown = markdown.Replace("&amp;", "&"); // Ampersand
markdown = markdown.Replace("&quot;", "\""); // Double quote
markdown = markdown.Replace("&apos;", "'"); // Single quote
markdown = markdown.Replace(" - ", "\n- "); // Convert bullet points to markdown list items
List<string> files = new List<string>();
files.AddRange(Directory.GetFiles("./"));
return markdown;
foreach (var file in files)
{
File.Move(file, file + ".bak");
}
}
private async Task CopyFolderContentOverCurrentFolder(string current, string otherFolder)
{
var files = Directory.GetFiles(otherFolder, "*.*", SearchOption.AllDirectories);
foreach (var file in files)
{
string relativePath = file.Replace(otherFolder, "");
string newPath = current + relativePath;
Directory.CreateDirectory(Path.GetDirectoryName(newPath));
File.Copy(file, newPath);
}
}
public async Task SelfUpdate(Update update, IProgress<float> progress)
{
Directory.CreateDirectory(_TempUpdateFolder);
string tempFile = $"./{_TempUpdateFolder}/update.zip";
string tempFolder = $"./{_TempUpdateFolder}/";
Directory.CreateDirectory(tempFolder);
await ServerCom.DownloadFileAsync(update.UpdateUrl, tempFile, progress);
await ArchiveManager.ExtractArchive(tempFile, tempFolder, progress, UnzipProgressType.PERCENTAGE_FROM_TOTAL_SIZE);
PrepareCurrentFolderForOverwrite();
if (OperatingSystem.IsWindows())
tempFolder += _WindowsUpdateFile;
else if (OperatingSystem.IsLinux())
tempFolder += _LinuxUpdateFile;
else if (OperatingSystem.IsMacOS())
tempFolder += _MacOSUpdateFile;
else throw new PlatformNotSupportedException();
await CopyFolderContentOverCurrentFolder("./", tempFolder.Substring(0, tempFolder.Length-4)); // Remove the .zip from the folder name
Process.Start("DiscordBot", "--update-cleanup");
Environment.Exit(0);
}
}

View File

@@ -5,19 +5,15 @@ namespace DiscordBotCore.Updater.Application
{
public class Update
{
public readonly static Update None = new Update(AppVersion.CurrentAppVersion, AppVersion.CurrentAppVersion, string.Empty, string.Empty);
public AppVersion UpdateVersion { get; private set; }
public AppVersion NewVersion { get; private set; }
public AppVersion CurrentVersion { get; private set; }
public string UpdateUrl { get; private set; }
public string UpdateNotes { get; private set; }
public Update(AppVersion currentVersion, AppVersion updateVersion, string updateUrl, string updateNotes)
public Update(AppVersion currentVersion, AppVersion updateVersion, string updateUrl)
{
UpdateVersion = updateVersion;
NewVersion = updateVersion;
CurrentVersion = currentVersion;
UpdateUrl = updateUrl;
UpdateNotes = updateNotes;
}
}
}