From 34afe3b7a44b51691c7ae87127c80848014e9ec0 Mon Sep 17 00:00:00 2001 From: HolographicHat Date: Wed, 15 Jun 2022 00:19:23 +0800 Subject: [PATCH] Implement export: paimon and csv --- YaeAchievement.csproj | 1 + src/Export.cs | 121 +++++++++++++++++++++++++++++++++++++++++- src/Program.cs | 20 ++++--- 3 files changed, 133 insertions(+), 9 deletions(-) diff --git a/YaeAchievement.csproj b/YaeAchievement.csproj index db57be3..c3db0d7 100644 --- a/YaeAchievement.csproj +++ b/YaeAchievement.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Export.cs b/src/Export.cs index c5e3b84..6e11e26 100644 --- a/src/Export.cs +++ b/src/Export.cs @@ -1,7 +1,124 @@ -namespace YaeAchievement; +using Newtonsoft.Json; +using static AchievementAllDataNotify.Types.Achievement.Types; + +namespace YaeAchievement; public static class Export { - public static void A() {} + public static void Choose(AchievementAllDataNotify data) { + Console.Write(@"导出至: + [0] 椰羊 (https://cocogoat.work/achievement) + [1] SnapGenshin + [2] Paimon.moe + [3] Seelie.me + [4] 表格文件 (默认) + 输入一个数字(0-4): ".Split("\n").Select(s => s.Trim()).JoinToString("\n") + " "); + if (!int.TryParse(Console.ReadLine(), out var num)) num = 4; + Action act = num switch { + 0 => ToCocogoat, + 1 => ToSnapGenshin, + 2 => ToPaimon, + 3 => ToSeelie, + 7 => ToRawJson, + _ => ToCSV + }; + act(data); + } + + private static void ToCocogoat(AchievementAllDataNotify data) { + throw new NotImplementedException(); + } + + private static void ToSnapGenshin(AchievementAllDataNotify data) { + throw new NotImplementedException(); + } + + private static void ToPaimon(AchievementAllDataNotify data) { + var info = LoadAchievementInfo(); + var output = new Dictionary>(); + var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-paimon.json"); + foreach (var ach in data.List.Where(a => a.Status is Status.Finished or Status.RewardTaken)) { + if (!info.Items.TryGetValue(ach.Id, out var achInfo) || achInfo == null) { + Console.WriteLine($"Unable to find {ach.Id} in metadata."); + continue; + } + var map = output.GetValueOrDefault(achInfo.Group, new Dictionary()); + map[ach.Id == 81222 ? 81219 : ach.Id] = true; + output[achInfo.Group] = map; + } + var final = new Dictionary>> { + ["achievement"] = output.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value) + }; + File.WriteAllText(path, JsonConvert.SerializeObject(final)); + Console.WriteLine($"成就数据已导出至 {path}"); + } + + private static void ToSeelie(AchievementAllDataNotify data) { + var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-seelie.json"); + Console.WriteLine($"成就数据已导出至 {path}"); + } + + // ReSharper disable once InconsistentNaming + private static void ToCSV(AchievementAllDataNotify data) { + var info = LoadAchievementInfo(); + var path = Path.GetFullPath($"achievement-{DateTime.Now:yyyyMMddHHmmss}.csv"); + var outList = new List>(); + foreach (var ach in data.List.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); + finishAt = DateTimeOffset.FromUnixTimeSeconds(ts).ToString("yyyy/MM/dd HH:mm:ss"); + } + var current = ach.Status != Status.Unfinished ? ach.Current == 0 ? ach.Total : ach.Current : ach.Current; + outList.Add(new List { + ach.Id, ach.Status.ToDesc(), achInfo.Group, achInfo.Name, + achInfo.Description, current, ach.Total, finishAt + }); + } + var output = new List { "ID,状态,特辑,名称,描述,当前进度,目标进度,完成时间" }; + output.AddRange(outList.OrderBy(v => v[2]).Select(item => { + item[2] = info.Group[(uint) item[2]]; + return item.JoinToString(","); + })); + File.WriteAllText(path, $"\uFEFF{string.Join("\n", output)}"); + Console.WriteLine($"成就数据已导出至 {path}"); + } + + private static void ToRawJson(AchievementAllDataNotify data) { + var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-raw.json"); + File.WriteAllText(path, JsonConvert.SerializeObject(data, Formatting.Indented)); + Console.WriteLine($"成就数据已导出至 {path}"); + } + + // ReSharper disable once InconsistentNaming + private static string ExportToUIAFApp(AchievementAllDataNotify data) { + return ""; + } + + private static string JoinToString(this IEnumerable list, string separator) { + return string.Join(separator, list); + } + + private static readonly List UnusedAchievement = new() { 84517 }; + + private static string ToDesc(this Status status) { + return status switch { + Status.Invalid => "未知", + Status.Finished => "已完成但未领取奖励", + Status.Unfinished => "未完成", + Status.RewardTaken => "已完成", + _ => throw new ArgumentOutOfRangeException(nameof(status), status, null) + }; + } + + private static AchievementInfo LoadAchievementInfo() { + var b = Utils.GetBucketFileAsByteArray("schicksal/metadata"); + return AchievementInfo.Parser.ParseFrom(b); + } } \ No newline at end of file diff --git a/src/Program.cs b/src/Program.cs index ad2d655..3756535 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -1,19 +1,25 @@ using System.Net; using System.Net.Http.Headers; +using Google.Protobuf; using YaeAchievement; using static YaeAchievement.Utils; +Console.WriteLine("----------------------------------------------------"); +Console.WriteLine("YaeAchievement - 原神成就导出工具"); +Console.WriteLine("https://github.com/HolographicHat/YaeAchievement"); +Console.WriteLine("----------------------------------------------------"); /*InstallExitHook(); InstallExceptionHook(); CheckGenshinIsRunning(); -LoadConfig();*/ -var ch = GetBucketFileAsString("latest.json"); +LoadConfig(); +CheckUpdate();*/ +TryDisableQuickEdit(); //Console.WriteLine(c.Send(msg).StatusCode); -return; +//using var o = File.OpenWrite("ai"); +//AchievementInfo.Parser.ParseJson(File.ReadAllText(@"C:\Users\holog\Desktop\cc.json")).WriteTo(o); StartAndWaitResult(@"D:\Genshin Impact Dev\2.8\YuanShen.exe", str => { GlobalVars.UnexpectedExit = false; - //AchievementAllDataNotify.Parser.ParseFrom(Convert.FromBase64String(str)).List; - //var notify = Serializer.Deserialize(stream)!; - //notify.list; - return false; + var list = AchievementAllDataNotify.Parser.ParseFrom(Convert.FromBase64String(str)); + Export.Choose(list); + return true; });