auto identify field ids

This commit is contained in:
HolographicHat
2024-11-21 07:31:21 +08:00
parent 4268b04f3c
commit 7d3d0f5e14
15 changed files with 235 additions and 119 deletions

View File

@@ -132,7 +132,7 @@ DWORD __stdcall ThreadProc(LPVOID hInstance)
}
initFuture.get();
MessagePipe = CreateFileA(R"(\\.\pipe\YaeAchievementPipe)", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
if (MessagePipe == INVALID_HANDLE_VALUE)
{

99
res/App.Designer.cs generated
View File

@@ -9,8 +9,8 @@
namespace YaeAchievement.res {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
@@ -22,15 +22,15 @@ namespace YaeAchievement.res {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class App {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal App() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
@@ -44,7 +44,7 @@ namespace YaeAchievement.res {
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
@@ -58,7 +58,7 @@ namespace YaeAchievement.res {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to all achievement.
/// </summary>
@@ -67,7 +67,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("AllAchievement", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please close another instance..
/// </summary>
@@ -76,7 +76,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("AnotherInstance", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to YaeAchievement ({0}).
/// </summary>
@@ -85,7 +85,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("AppBanner", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You need to login genshin impact before exporting..
/// </summary>
@@ -94,7 +94,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ConfigNeedStartGenshin", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Download: {0}.
/// </summary>
@@ -103,7 +103,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("DownloadLink", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Network error ({0}: {1}).
/// </summary>
@@ -112,9 +112,9 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExceptionNetwork", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Export to:
/// Looks up a localized string similar to Export to:
///[0] Cocogoat (https://cocogoat.work/achievement, Default)
///[1] Snap.HuTao
///[2] Paimon.moe
@@ -130,7 +130,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportChoose", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Fail, please contact developer to get help information.
/// </summary>
@@ -139,7 +139,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToCocogoatFail", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully exported to cocogoat..
/// </summary>
@@ -148,7 +148,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToCocogoatSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully exported to {0}.
/// </summary>
@@ -157,7 +157,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToFileSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please update Snap Hutao and retry..
/// </summary>
@@ -166,7 +166,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToSnapGenshinNeedUpdate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully exported to Snap Hutao..
/// </summary>
@@ -175,7 +175,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToSnapGenshinSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please launch/update Teyvat Guide and retry..
/// </summary>
@@ -184,7 +184,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToTauriFail", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully exported to Teyvat Guide..
/// </summary>
@@ -193,7 +193,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToTauriSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}.
/// </summary>
@@ -202,7 +202,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToWxApp1Success", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please update xunkong and retry..
/// </summary>
@@ -211,7 +211,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToXunkongNeedUpdate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully exported to xunkong..
/// </summary>
@@ -220,7 +220,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToXunkongSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Game process start ({0}).
/// </summary>
@@ -229,7 +229,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("GameLoading", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Game exited..
/// </summary>
@@ -238,7 +238,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("GameProcessExit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please update genshin and retry..
/// </summary>
@@ -247,7 +247,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("GenshinHashError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please close game before run this application. ({0}).
/// </summary>
@@ -256,7 +256,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("GenshinIsRunning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Network error:.
/// </summary>
@@ -265,7 +265,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("NetworkError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No write permission on {0}..
/// </summary>
@@ -274,7 +274,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("NoWritePermission", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Press any key to exit..
/// </summary>
@@ -283,7 +283,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("PressKeyToExit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Reward not taken.
/// </summary>
@@ -292,7 +292,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("StatusFinished", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid.
/// </summary>
@@ -301,7 +301,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("StatusInvalid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Finished.
/// </summary>
@@ -310,7 +310,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("StatusRewardTaken", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unfinished.
/// </summary>
@@ -319,9 +319,9 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("StatusUnfinished", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Description:
/// Looks up a localized string similar to Description:
///{0}.
/// </summary>
internal static string UpdateDescription {
@@ -329,7 +329,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("UpdateDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Downloading update package....
/// </summary>
@@ -338,7 +338,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("UpdateDownloading", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Has update: {0} =&gt; {1}.
/// </summary>
@@ -347,7 +347,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("UpdateNewVersion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
@@ -357,7 +357,7 @@ namespace YaeAchievement.res {
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to Upload error to appcenter....
/// </summary>
@@ -366,7 +366,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("UploadError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use previous fetched data? (yes|no).
/// </summary>
@@ -375,7 +375,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("UsePreviousData", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Downloading Visual C++ Redistributable....
/// </summary>
@@ -384,7 +384,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("VcRuntimeDownload", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Installing Visual C++ Redistributable....
/// </summary>
@@ -393,5 +393,14 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("VcRuntimeInstalling", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please update game and retry..
/// </summary>
internal static string WaitMetadataUpdate {
get {
return ResourceManager.GetString("WaitMetadataUpdate", resourceCulture);
}
}
}
}

View File

@@ -137,4 +137,7 @@ Input a number (0-8): </value>
<data name="ExportToTauriFail" xml:space="preserve">
<value>Please launch/update Teyvat Guide and retry.</value>
</data>
<data name="WaitMetadataUpdate" xml:space="preserve">
<value>Please update game and retry.</value>
</data>
</root>

View File

@@ -127,4 +127,7 @@
<data name="ExportToTauriSuccess" xml:space="preserve">
<value>在 Teyvat Guide 进行下一步操作</value>
</data>
<data name="WaitMetadataUpdate" xml:space="preserve">
<value>当前元数据版本不匹配,请更新原神至最新版本或等待元数据更新后重试。</value>
</data>
</root>

View File

@@ -1,21 +0,0 @@
syntax = "proto3";
option csharp_namespace = "Proto";
message Achievement {
enum Status {
INVALID = 0;
UNFINISHED = 1;
FINISHED = 2;
REWARD_TAKEN = 3;
}
uint32 timestamp = 11;
uint32 current = 5;
uint32 total = 15;
uint32 id = 2;
Status status = 7;
}
message AchievementAllDataNotify {
repeated Achievement list = 4;
}

View File

@@ -2,6 +2,14 @@ syntax = "proto3";
option csharp_namespace = "Proto";
message AchievementProtoFieldInfo {
uint32 id = 1;
uint32 status = 2;
uint32 total_progress = 3;
uint32 current_progress = 4;
uint32 finish_timestamp = 5;
}
message AchievementItem {
uint32 pre = 1;
uint32 group = 2;
@@ -13,4 +21,5 @@ message AchievementInfo {
string version = 1;
map<uint32, string> group = 2;
map<uint32, AchievementItem> items = 3;
AchievementProtoFieldInfo pb_info = 4;
}

View File

@@ -3,13 +3,13 @@ syntax = "proto3";
option csharp_namespace = "Proto";
message UpdateInfo {
uint32 versionCode = 1;
string versionName = 2;
uint32 version_code = 1;
string version_name = 2;
string description = 3;
string packageLink = 4;
bool forceUpdate = 5;
bool enableLibDownload = 6;
bool enableAutoDownload = 7;
string currentCNGameHash = 8;
string currentOSGameHash = 9;
string package_link = 4;
bool force_update = 5;
bool enable_lib_download = 6;
bool enable_auto_update = 7;
string current_cn_hash = 8;
string current_os_hash = 9;
}

View File

@@ -5,9 +5,8 @@ using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Win32;
using Proto;
using YaeAchievement.Parsers;
using YaeAchievement.res;
using static Proto.Achievement.Types;
namespace YaeAchievement;
@@ -120,10 +119,10 @@ public static class Export {
}
private static void ToPaimon(AchievementAllDataNotify data) {
var info = LoadAchievementInfo().Items.ToDictionary(pair => pair.Key, pair => pair.Value.Group);
var info = GlobalVars.AchievementInfo.Items.ToDictionary(pair => pair.Key, pair => pair.Value.Group);
var final = new Dictionary<string, Dictionary<uint, Dictionary<uint, bool>>> {
["achievement"] = data.List
.Where(achievement => achievement.Status is Status.Finished or Status.RewardTaken)
["achievement"] = data.AchievementList
.Where(achievement => achievement.Status is AchievementStatus.Finished or AchievementStatus.RewardTaken)
.Where(achievement => info.ContainsKey(achievement.Id))
.GroupBy(achievement => info[achievement.Id], achievement => achievement.Id)
.OrderBy(group => group.Key)
@@ -137,7 +136,7 @@ public static class Export {
private static void ToSeelie(AchievementAllDataNotify data) {
var output = new Dictionary<uint, Dictionary<string, bool>>();
foreach (var ach in data.List.Where(a => a.Status is Status.Finished or Status.RewardTaken)) {
foreach (var ach in data.AchievementList.Where(a => a.Status is AchievementStatus.Finished or AchievementStatus.RewardTaken)) {
output[ach.Id] = new Dictionary<string, bool> {
["done"] = true
};
@@ -153,23 +152,25 @@ public static class Export {
// ReSharper disable once InconsistentNaming
private static void ToCSV(AchievementAllDataNotify data) {
var info = LoadAchievementInfo();
var info = GlobalVars.AchievementInfo;
var outList = new List<List<object>>();
foreach (var ach in data.List.OrderBy(a => a.Id)) {
foreach (var ach in data.AchievementList.OrderBy(a => a.Id)) {
if (UnusedAchievement.Contains(ach.Id)) continue;
if (!info.Items.TryGetValue(ach.Id, out var achInfo) || achInfo == null) {
Console.WriteLine($@"Unable to find {ach.Id} in metadata.");
continue;
}
var finishAt = "";
if (ach.Timestamp != 0) {
var ts = Convert.ToInt64(ach.Timestamp);
if (ach.FinishTimestamp != 0) {
var ts = Convert.ToInt64(ach.FinishTimestamp);
finishAt = DateTimeOffset.FromUnixTimeSeconds(ts).ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss");
}
var current = ach.Status != Status.Unfinished ? ach.Current == 0 ? ach.Total : ach.Current : ach.Current;
var current = ach.Status != AchievementStatus.Unfinished
? ach.CurrentProgress == 0 ? ach.TotalProgress : ach.CurrentProgress
: ach.CurrentProgress;
outList.Add([
ach.Id, ach.Status.ToDesc(), achInfo.Group, achInfo.Name,
achInfo.Description, current, ach.Total, finishAt
achInfo.Description, current, ach.TotalProgress, finishAt
]);
}
var output = new List<string> { "ID,状态,特辑,名称,描述,当前进度,目标进度,完成时间" };
@@ -194,13 +195,13 @@ public static class Export {
// ReSharper disable once InconsistentNaming
private static Dictionary<string, object> ExportToUIAFApp(AchievementAllDataNotify data) {
var output = data.List
.Where(a => (uint)a.Status > 1 || a.Current > 0)
var output = data.AchievementList
.Where(a => (uint)a.Status > 1 || a.CurrentProgress > 0)
.Select(ach => new Dictionary<string, uint> {
["id"] = ach.Id,
["status"] = (uint) ach.Status,
["current"] = ach.Current,
["timestamp"] = ach.Timestamp
["current"] = ach.CurrentProgress,
["timestamp"] = ach.FinishTimestamp
})
.ToList();
return new Dictionary<string, object> {
@@ -225,21 +226,16 @@ public static class Export {
private static readonly List<uint> UnusedAchievement = [ 84517 ];
private static string ToDesc(this Status status) {
private static string ToDesc(this AchievementStatus status) {
return status switch {
Status.Invalid => App.StatusInvalid,
Status.Finished => App.StatusFinished,
Status.Unfinished => App.StatusUnfinished,
Status.RewardTaken => App.StatusRewardTaken,
AchievementStatus.Invalid => App.StatusInvalid,
AchievementStatus.Finished => App.StatusFinished,
AchievementStatus.Unfinished => App.StatusUnfinished,
AchievementStatus.RewardTaken => App.StatusRewardTaken,
_ => throw new ArgumentOutOfRangeException(nameof(status), status, null)
};
}
private static AchievementInfo LoadAchievementInfo() {
var b = Utils.GetBucketFileAsByteArray("schicksal/metadata");
return AchievementInfo.Parser.ParseFrom(b);
}
public static int PrintMsgAndReturnErrCode(this Win32Exception ex, string msg) {
// ReSharper disable once LocalizableElement
Console.WriteLine($"{msg}: {ex.Message}");

View File

@@ -1,4 +1,5 @@
using System.Reflection;
using Proto;
namespace YaeAchievement;
@@ -26,6 +27,9 @@ public static class GlobalVars {
public const string PipeName = "YaeAchievementPipe";
public const string BucketHost = "https://cn-cd-1259389942.file.myqcloud.com";
public static AchievementInfo AchievementInfo { get; }
= AchievementInfo.Parser.ParseFrom(Utils.GetBucketFileAsByteArray("schicksal/metadata"));
static GlobalVars() {
Directory.CreateDirectory(DataPath);
Directory.CreateDirectory(CachePath);

0
src/Outputs/.gitkeep Normal file
View File

View File

@@ -0,0 +1,97 @@
using System.Runtime.CompilerServices;
using Google.Protobuf;
using YaeAchievement.res;
namespace YaeAchievement.Parsers;
public enum AchievementStatus {
Invalid,
Unfinished,
Finished,
RewardTaken,
}
public class AchievementItem {
public uint Id { get; init; }
public uint TotalProgress { get; init; }
public uint CurrentProgress { get; init; }
public uint FinishTimestamp { get; init; }
public AchievementStatus Status { get; init; }
}
public class AchievementAllDataNotify {
public List<AchievementItem> AchievementList { get; private init; } = [];
public static AchievementAllDataNotify ParseFrom(byte[] bytes) {
using var stream = new CodedInputStream(bytes);
uint tag;
var data = new List<Dictionary<uint, uint>>();
while ((tag = stream.ReadTag()) != 0) {
if ((tag & 7) == 2) { // is LengthDelimited
var dict = new Dictionary<uint, uint>();
using var eStream = new CodedInputStream(ReadRawBytes(stream, stream.ReadLength()));
while ((tag = eStream.ReadTag()) != 0) {
if ((tag & 7) != 0) { // not VarInt
dict = null;
break;
}
dict[tag >> 3] = eStream.ReadUInt32();
}
if (dict != null) {
data.Add(dict);
}
}
}
if (data.Count == 0) {
return new AchievementAllDataNotify();
}
uint tId, sId, iId, currentId, totalId;
if (data.Count > 20) { /* uwu */
(tId, var cnt) = data // ↓ 2020-09-15 04:15:14
.GroupKeys(value => value > 1600114514).Select(g => (g.Key, g.Count())).MaxBy(p => p.Item2);
sId = data // FINISHED ↓ ↓ REWARD_TAKEN
.GroupKeys(value => value is 2 or 3).First(g => g.Count() == cnt).Key;
iId = data // ↓ id: 8xxxx
.GroupKeys(value => value / 10000 % 10 == 8).MaxBy(g => g.Count())!.Key;
(currentId, totalId) = data
.Where(d => d[sId] is 2 or 3)
.Select(d => d.ToDictionary().RemoveValues(tId, sId, iId).ToArray())
.Where(d => d.Length == 2 && d[0].Value != d[1].Value)
.GroupBy(a => a[0].Value > a[1].Value ? (a[0].Key, a[1].Key) : (a[1].Key, a[0].Key))
.Select(g => (FieldIds: g.Key, Count: g.Count()))
.MaxBy(p => p.Count)
.FieldIds;
#if DEBUG
// ReSharper disable once LocalizableElement
Console.WriteLine($"Id={iId}, Status={sId}, Total={totalId}, Current={currentId}, Timestamp={tId}");
#endif
} else {
var info = GlobalVars.AchievementInfo.PbInfo; // ...
iId = info.Id;
tId = info.FinishTimestamp;
sId = info.Status;
totalId = info.TotalProgress;
currentId = info.CurrentProgress;
if (data.Any(dict => !dict.ContainsKey(iId) || !dict.ContainsKey(sId) || !dict.ContainsKey(totalId))) {
Console.WriteLine(App.WaitMetadataUpdate);
Environment.Exit(0);
}
}
return new AchievementAllDataNotify {
AchievementList = data.Select(dict => new AchievementItem {
Id = dict[iId],
Status = (AchievementStatus) dict[sId],
TotalProgress = dict[totalId],
CurrentProgress = dict.GetValueOrDefault(currentId),
FinishTimestamp = dict.GetValueOrDefault(tId),
}).ToList()
};
}
[UnsafeAccessor(UnsafeAccessorKind.Method)]
private static extern byte[] ReadRawBytes(CodedInputStream stream, int size);
}

View File

@@ -1,6 +1,6 @@
using System.Text;
using Proto;
using YaeAchievement;
using YaeAchievement.Parsers;
using YaeAchievement.res;
using static YaeAchievement.Utils;
@@ -29,7 +29,7 @@ var historyCache = new CacheFile("ExportData");
AchievementAllDataNotify? data = null;
try {
data = AchievementAllDataNotify.Parser.ParseFrom(historyCache.Read().Content);
data = AchievementAllDataNotify.ParseFrom(historyCache.Read().Content.ToByteArray());
} catch (Exception) { /* ignored */ }
if (historyCache.LastWriteTime.AddMinutes(60) > DateTime.UtcNow && data != null) {
@@ -43,7 +43,7 @@ if (historyCache.LastWriteTime.AddMinutes(60) > DateTime.UtcNow && data != null)
StartAndWaitResult(AppConfig.GamePath, str => {
GlobalVars.UnexpectedExit = false;
var bytes = Convert.FromBase64String(str);
var list = AchievementAllDataNotify.Parser.ParseFrom(bytes);
var list = AchievementAllDataNotify.ParseFrom(bytes);
historyCache.Write(bytes);
Export.Choose(list);
return true;

View File

@@ -0,0 +1,16 @@
// ReSharper disable once CheckNamespace
namespace System.Collections.Generic;
public static class Collection {
public static IDictionary<TKey, TValue> RemoveValues<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
params TKey[] keys
) {
foreach (var key in keys) {
dictionary.Remove(key);
}
return dictionary;
}
}

View File

@@ -0,0 +1,14 @@
// ReSharper disable once CheckNamespace
namespace System.Linq;
public static class Enumerable {
public static IEnumerable<IGrouping<TKey, TKey>> GroupKeys<TKey, TValue>(
this IEnumerable<Dictionary<TKey, TValue>> source,
Func<TValue, bool> condition
) where TKey : notnull {
return source.SelectMany(dict => dict.Where(pair => condition(pair.Value)).Select(pair => pair.Key)).GroupBy(x => x);
}
}

View File

@@ -93,7 +93,7 @@ public static class Utils {
if (GlobalVars.AppVersionCode < info.VersionCode) {
Console.WriteLine(App.UpdateNewVersion, GlobalVars.AppVersionName, info.VersionName);
Console.WriteLine(App.UpdateDescription, info.Description);
if (info.EnableAutoDownload) {
if (info.EnableAutoUpdate) {
Console.WriteLine(App.UpdateDownloading);
var tmpPath = Path.GetTempFileName();
File.WriteAllBytes(tmpPath, GetBucketFileAsByteArray(info.PackageLink));
@@ -205,22 +205,8 @@ public static class Utils {
};
}
private static bool CheckGenshinIsLatestVersion(string path) {
#if DEBUG
return true;
#else
if (!File.Exists(path)) return false;
var hash = File.ReadAllBytes(path).MD5Hash();
return hash == _updateInfo.CurrentCNGameHash || hash == _updateInfo.CurrentOSGameHash;
#endif
}
// ReSharper disable once UnusedMethodReturnValue.Global
public static Thread StartAndWaitResult(string exePath, Func<string, bool> onReceive) {
if (!CheckGenshinIsLatestVersion(exePath)) {
Console.WriteLine(App.GenshinHashError);
Environment.Exit(0);
}
AppDomain.CurrentDomain.ProcessExit += (_, _) => {
try {
File.Delete(GlobalVars.LibFilePath);