小优化及新增脚本仓库桥接支持 (#1952)

This commit is contained in:
躁动的氨气
2025-08-02 17:31:41 +08:00
committed by GitHub
parent 55667d2627
commit 1add385e8a
5 changed files with 448 additions and 71 deletions

View File

@@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Policy;
using System.Threading.Tasks;
using BetterGenshinImpact.ViewModel.Message;
using CommunityToolkit.Mvvm.Messaging;
using Wpf.Ui.Violeta.Controls;
using Newtonsoft.Json.Linq;
namespace BetterGenshinImpact.Core.Script.WebView;
@@ -16,31 +16,31 @@ namespace BetterGenshinImpact.Core.Script.WebView;
/// </summary>
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class RepoWebBridge
public sealed class RepoWebBridge
{
private static readonly HashSet<string> AllowedTextExtensions = new(StringComparer.OrdinalIgnoreCase)
{
".txt", ".md", ".json", ".js", ".ts",
".vue", ".css", ".html", ".csv", ".xml",
".yaml", ".yml", ".ini", ".config"
};
public async Task<string> GetRepoJson()
{
try
{
if (!Directory.Exists(ScriptRepoUpdater.CenterRepoPath))
{
throw new Exception("仓库文件夹不存在,请至少成功更新一次仓库!");
throw new InvalidOperationException("仓库文件夹不存在,请至少成功更新一次仓库!");
}
var localRepoJsonPath = Directory
.GetFiles(ScriptRepoUpdater.CenterRepoPath, "repo.json", SearchOption.AllDirectories).FirstOrDefault();
if (localRepoJsonPath is null)
{
throw new Exception("repo.json 仓库索引文件不存在,请至少成功更新一次仓库!");
}
var json = await File.ReadAllTextAsync(localRepoJsonPath);
return json;
string localRepoJsonPath = GetRepoJsonPath();
return await File.ReadAllTextAsync(localRepoJsonPath);
}
catch (Exception e)
catch (Exception ex)
{
await MessageBox.ShowAsync(e.Message, "获取仓库信息失败");
return "";
await MessageBox.ShowAsync(ex.Message, "获取仓库信息失败");
return string.Empty;
}
}
@@ -59,21 +59,15 @@ public class RepoWebBridge
public async Task<string> GetUserConfigJson()
{
try
string userConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "User", "config.json");
if (!File.Exists(userConfigPath))
{
string userConfigPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "User", "config.json");
if (!File.Exists(userConfigPath))
{
throw new Exception("用户配置文件不存在: " + userConfigPath);
}
await MessageBox.ShowAsync($"用户配置文件不存在: {userConfigPath}", "获取用户配置失败");
return string.Empty;
}
return await File.ReadAllTextAsync(userConfigPath);
}
catch (Exception e)
{
await MessageBox.ShowAsync(e.Message, "获取用户配置失败");
return "";
}
return await File.ReadAllTextAsync(userConfigPath);
}
public async Task<string> GetFile(string relPath)
@@ -81,31 +75,131 @@ public class RepoWebBridge
try
{
string filePath = Path.Combine(ScriptRepoUpdater.CenterRepoPath, "repo", relPath)
.Replace('/', Path.DirectorySeparatorChar);
.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
if (!File.Exists(filePath))
return "404";
// 允许返回内容的文本文件扩展名
string[] allowedTextExtensions = {
".txt", ".md", ".json", ".js", ".ts",
".vue", ".css", ".html", ".csv", ".xml",
".yaml", ".yml", ".ini", ".config"
};
string ext = Path.GetExtension(filePath).ToLower();
if (allowedTextExtensions.Contains(ext))
{
return await File.ReadAllTextAsync(filePath);
return "404";
}
// 其他所有文件类型返回404
return "404";
string extension = Path.GetExtension(filePath);
return AllowedTextExtensions.Contains(extension)
? await File.ReadAllTextAsync(filePath)
: "404";
}
catch
{
return "404";
}
}
public async Task<bool> UpdateSubscribed(string path)
{
try
{
if (!Directory.Exists(ScriptRepoUpdater.CenterRepoPath))
{
throw new InvalidOperationException("仓库文件夹不存在,请至少成功更新一次仓库!");
}
string localRepoJsonPath = GetRepoJsonPath();
string json = await File.ReadAllTextAsync(localRepoJsonPath);
var jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject>(json);
if (jsonObj?["indexes"] is not JArray indexes) return false;
string[] pathParts = path.Split('/');
ProcessPathRecursively(indexes, pathParts, 0);
string modifiedJson = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
await File.WriteAllTextAsync(localRepoJsonPath, modifiedJson);
return true;
}
catch (Exception ex)
{
await MessageBox.ShowAsync(ex.Message, "信息更新失败");
return false;
}
}
public async Task<bool> ClearUpdate()
{
try
{
string? repoJsonPath = Directory
.GetFiles(ScriptRepoUpdater.CenterRepoPath, "repo.json", SearchOption.AllDirectories)
.FirstOrDefault();
if (string.IsNullOrEmpty(repoJsonPath))
{
throw new FileNotFoundException("找不到原始 repo.json 文件");
}
string targetPath = Path.Combine(ScriptRepoUpdater.ReposPath, "repo_updated.json");
File.Copy(repoJsonPath, targetPath, overwrite: true);
return true;
}
catch (Exception ex)
{
await MessageBox.ShowAsync($"清空更新标记失败: {ex.Message}", "操作失败");
return false;
}
}
private static string GetRepoJsonPath()
{
string updatedRepoJsonPath = Path.Combine(
Path.GetDirectoryName(Path.Combine(ScriptRepoUpdater.ReposPath, "bettergi-scripts-list-git"))!,
"repo_updated.json"
);
if (File.Exists(updatedRepoJsonPath))
{
return updatedRepoJsonPath;
}
string? repoJson = Directory
.GetFiles(ScriptRepoUpdater.CenterRepoPath, "repo.json", SearchOption.AllDirectories)
.FirstOrDefault();
return repoJson ?? throw new FileNotFoundException("repo.json 仓库索引文件不存在,请至少成功更新一次仓库!");
}
private static void ProcessPathRecursively(JArray array, string[] pathParts, int currentIndex)
{
foreach (JObject item in array.OfType<JObject>())
{
if (item["name"]?.ToString() != pathParts[currentIndex]) continue;
if (currentIndex == pathParts.Length - 1)
{
ResetHasUpdateFlag(item);
}
else if (item["children"] is JArray children)
{
ProcessPathRecursively(children, pathParts, currentIndex + 1);
}
break;
}
}
private static void ResetHasUpdateFlag(JObject node)
{
if (node["hasUpdate"] is { Type: JTokenType.Boolean } hasUpdate &&
(bool)hasUpdate)
{
node["hasUpdate"] = false;
}
if (node["children"] is JArray children)
{
foreach (JObject child in children.OfType<JObject>())
{
ResetHasUpdateFlag(child);
}
}
}
}