1
0
mirror of synced 2025-11-06 03:40:37 +08:00
Files
RevokeMsgPatcher/RevokeMsgPatcher/Model/LiteLoaderRowData.cs
2024-09-28 22:58:38 +08:00

297 lines
9.8 KiB
C#

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using RevokeMsgPatcher.Model.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Application = System.Windows.Forms.Application;
namespace RevokeMsgPatcher.Model
{
internal class LiteLoaderRowData
{
public static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
public string Name { get; set; }
public string NameLink { get; set; }
public string Author { get; set; }
public string AuthorLink { get; set; }
public string Status { get; set; }
public event Action<string> StatusUpdated;
public DataGridViewRow Row { get; set; }
/// <summary>
/// 本地存储的目录
/// </summary>
public string LocalPath { get; set; }
/// <summary>
/// 主干名称
/// </summary>
public string MainBranchName { get; set; }
private void UpdateStatus(string newStatus)
{
Status = newStatus;
StatusUpdated?.Invoke(newStatus);
}
/// <summary>
/// 由于这个 api.github.com 没有加速的方式,所以不用了
/// </summary>
[Obsolete("由于这个 api.github.com 没有加速的方式,所以不用了")]
public string ReleasesApi
{
get
{
var repo = NameLink.Replace(@"https://github.com", @"https://api.github.com/repos");
return repo + @"/releases/latest";
}
}
public string DownloadUrl { get; set; }
public string VersionJsonUrl
{
get
{
var repo = NameLink.Replace(@"https://github.com", @"https://raw.githubusercontent.com");
if (NameLink == "https://github.com/LiteLoaderQQNT/LiteLoaderQQNT")
{
return repo + $@"/refs/heads/{MainBranchName}/package.json";
}
else
{
return repo + $@"/refs/heads/{MainBranchName}/manifest.json";
}
}
}
public string GetLocalVersion()
{
if (NameLink.Contains("QQNTFileVerifyPatch"))
{
return null;
}
if (!Directory.Exists(LocalPath))
{
Directory.CreateDirectory(LocalPath);
}
string path = null;
path = Path.Combine(LocalPath, NameLink == "https://github.com/LiteLoaderQQNT/LiteLoaderQQNT" ? "package.json" : "manifest.json");
if (File.Exists(path))
{
var json = File.ReadAllText(path);
var package = JsonConvert.DeserializeObject<VersionJson>(json, SerializerSettings);
return package.Version;
}
return null;
}
public void GetLocalVersionAndUpdateStatus()
{
var localVersion = GetLocalVersion();
if (localVersion != null)
{
UpdateStatus($"当前版本{localVersion}");
}
else
{
UpdateStatus("未检查");
}
}
public async Task<string> GetRemoteVersion()
{
using (var client = new HttpClient())
{
var response = await client.GetAsync(VersionJsonUrl);
Debug.WriteLine(response.Content);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
var package = JsonConvert.DeserializeObject<VersionJson>(json, SerializerSettings);
return package.Version;
}
return null;
}
}
public async Task CheckAndUpdate()
{
try
{
if (NameLink.Contains("QQNTFileVerifyPatch"))
{
return;
}
string localVersion = GetLocalVersion();
string remoteVersion = await GetRemoteVersion();
if (localVersion == null || new Version(remoteVersion) > new Version(localVersion))
{
UpdateStatus($"存在新版本{remoteVersion},正在下载...");
Debug.WriteLine("发现新版本,正在下载...");
string downloadedFilePath = await DownloadLatestPackage(DownloadUrl.Replace("#{version}", remoteVersion), Path.Combine(Application.StartupPath, "Public/Download"));
Debug.WriteLine("下载到:" + downloadedFilePath);
UpdateStatus($"下载成功,解压中...");
// 解压
string zipFileName = Path.GetFileNameWithoutExtension(downloadedFilePath);
string extractPath = Path.Combine(Application.StartupPath, "Public/Extracted", zipFileName);
if (Directory.Exists(extractPath))
{
Directory.Delete(extractPath, true);
}
Directory.CreateDirectory(extractPath);
ZipFile.ExtractToDirectory(downloadedFilePath, extractPath);
Debug.WriteLine("解压至:" + extractPath);
UpdateStatus($"解压成功,替换中...");
// 找到根目录
string pluginPath = FindDirectoryWithJson(extractPath);
Debug.WriteLine("解压后的插件/本体目录:" + pluginPath);
// 拷贝
DirectoryCopy(pluginPath, LocalPath);
Debug.WriteLine("拷贝至:" + LocalPath);
// 清理
if (File.Exists(downloadedFilePath))
{
File.Delete(downloadedFilePath);
}
if (Directory.Exists(extractPath))
{
Directory.Delete(extractPath, true);
}
Debug.WriteLine("清理完成。");
UpdateStatus($"{remoteVersion}更新完成");
}
else
{
UpdateStatus($"已是最新版本{localVersion}");
Debug.WriteLine("当前已是最新版本。");
}
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
UpdateStatus(Status + " 后发生异常:" + e.Message);
}
}
private string FindDirectoryWithJson(string extractPath, int maxDepth = 2)
{
return FindDirectoryWithJsonRecursive(extractPath, maxDepth, 0);
}
private string FindDirectoryWithJsonRecursive(string currentPath, int maxDepth, int currentDepth)
{
if (currentDepth > maxDepth)
{
return null;
}
string[] jsonFiles = { "package.json", "manifest.json" };
foreach (var jsonFile in jsonFiles)
{
if (File.Exists(Path.Combine(currentPath, jsonFile)))
{
return currentPath;
}
}
if (currentDepth < maxDepth)
{
foreach (var directory in Directory.GetDirectories(currentPath))
{
var result = FindDirectoryWithJsonRecursive(directory, maxDepth, currentDepth + 1);
if (result != null)
{
return result;
}
}
}
return null;
}
private async Task<string> DownloadLatestPackage(string url, string localDirectory)
{
using (HttpClient client = new HttpClient())
{
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsByteArrayAsync();
var fileName = Path.GetFileName(url);
var localPath = Path.Combine(localDirectory, fileName);
Directory.CreateDirectory(localDirectory); // 确保目录存在
File.WriteAllBytes(localPath, data);
return localPath;
}
else
{
throw new Exception("下载失败");
}
}
}
private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs = true)
{
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
DirectoryInfo[] dirs = dir.GetDirectories();
if (!dir.Exists)
{
throw new DirectoryNotFoundException("源目录不存在: " + sourceDirName);
}
if (!Directory.Exists(destDirName))
{
Directory.CreateDirectory(destDirName);
}
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string tempPath = Path.Combine(destDirName, file.Name);
file.CopyTo(tempPath, true);
}
if (copySubDirs)
{
foreach (DirectoryInfo subdir in dirs)
{
string tempPath = Path.Combine(destDirName, subdir.Name);
DirectoryCopy(subdir.FullName, tempPath, copySubDirs);
}
}
}
}
}