mirror of
https://github.com/HolographicHat/Yae.git
synced 2025-12-13 18:08:15 +08:00
@@ -1,82 +0,0 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using YaeAchievement.AppCenterSDK.Models;
|
||||
using YaeAchievement.AppCenterSDK.Models.Serialization;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK;
|
||||
|
||||
public static class AppCenter {
|
||||
|
||||
private const string AppSecret = "648b83bf-d439-49bd-97f4-e1e506bdfe39";
|
||||
private const string ApiUrl = "https://in.appcenter.ms/logs?api-version=1.0.0";
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
public static Guid? SessionID { get; private set; }
|
||||
public static readonly string DeviceID;
|
||||
public static readonly Device DeviceInfo;
|
||||
private static List<Log> Queue;
|
||||
private static readonly Lazy<HttpClient> httpClient = new(() => new HttpClient(new HttpClientHandler {
|
||||
Proxy = GlobalVars.DebugProxy ? new WebProxy("http://127.0.0.1:8888") : null
|
||||
}) {
|
||||
DefaultRequestHeaders = {
|
||||
{ "Install-ID", DeviceID },
|
||||
{ "App-Secret", AppSecret }
|
||||
}
|
||||
});
|
||||
|
||||
static AppCenter() {
|
||||
Queue = new List<Log>();
|
||||
DeviceID = DeviceHelper.GetDeviceID();
|
||||
DeviceInfo = new Device();
|
||||
var running = true;
|
||||
Task.Run(() => {
|
||||
// ReSharper disable once LoopVariableIsNeverChangedInsideLoop
|
||||
while (running) {
|
||||
Upload();
|
||||
Thread.Sleep(5 * 1000);
|
||||
}
|
||||
});
|
||||
AppDomain.CurrentDomain.ProcessExit += (_, _) => {
|
||||
running = false;
|
||||
};
|
||||
}
|
||||
|
||||
// ReSharper restore InconsistentNaming
|
||||
public static void Upload() {
|
||||
if (Queue.Count == 0) return;
|
||||
var uploadStatus = "";
|
||||
do {
|
||||
Queue = Queue.Select(log => {
|
||||
log.Status = LogStatus.Uploading;
|
||||
return log;
|
||||
}).ToList();
|
||||
using var uploadContent = new StringContent(Queue.ToJson());
|
||||
try {
|
||||
using var response = httpClient.Value.PostAsync(ApiUrl, uploadContent).Result;
|
||||
var result = response.Content.ReadFromJsonAsync<LogUploadResult>().GetAwaiter().GetResult();
|
||||
uploadStatus = result!.Status;
|
||||
} catch (Exception) {
|
||||
// ignored
|
||||
}
|
||||
} while (uploadStatus != "Success");
|
||||
Queue.RemoveAll(log => log.Status == LogStatus.Uploading);
|
||||
}
|
||||
|
||||
public static void Init() {
|
||||
new StartServiceLog("Analytics", "Crashes").Enqueue();
|
||||
SessionID = Guid.NewGuid();
|
||||
new StartSessionLog().Enqueue();
|
||||
}
|
||||
|
||||
public static void TrackCrash(Exception exception, bool fatal = true) {
|
||||
new ManagedErrorLog(exception, fatal).Enqueue();
|
||||
}
|
||||
|
||||
public static void Enqueue(this Log log) {
|
||||
Queue.Add(log);
|
||||
}
|
||||
|
||||
private static string ToJson(this IEnumerable<Log> queue) {
|
||||
return LogSerializer.Serialize(new LogContainer(queue));
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using Microsoft.Win32;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Gdi;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK;
|
||||
|
||||
#pragma warning disable CA1416
|
||||
public static class DeviceHelper {
|
||||
|
||||
public static string? GetOem() {
|
||||
using var root = Registry.LocalMachine;
|
||||
using var sub = root.OpenSubKey("HARDWARE\\DESCRIPTION\\System\\BIOS");
|
||||
var oem = sub?.GetValue("SystemManufacturer") as string;
|
||||
return oem == "System manufacturer" ? null : oem;
|
||||
}
|
||||
|
||||
public static string? GetModel() {
|
||||
using var root = Registry.LocalMachine;
|
||||
using var sub = root.OpenSubKey("HARDWARE\\DESCRIPTION\\System\\BIOS");
|
||||
var model = sub?.GetValue("SystemProductName") as string;
|
||||
return model == "System Product Name" ? null : model;
|
||||
}
|
||||
|
||||
public static string GetScreenSize() {
|
||||
var desktop = Native.GetDC(HWND.Null);
|
||||
var size = $"{Native.GetDeviceCaps(desktop, GET_DEVICE_CAPS_INDEX.DESKTOPHORZRES)}x{Native.GetDeviceCaps(desktop, GET_DEVICE_CAPS_INDEX.DESKTOPVERTRES)}";
|
||||
_ = Native.ReleaseDC(HWND.Null, desktop);
|
||||
return size;
|
||||
}
|
||||
|
||||
public static string? GetCountry() {
|
||||
using var root = Registry.CurrentUser;
|
||||
using var sub = root.OpenSubKey("Control Panel\\International\\Geo");
|
||||
return sub?.GetValue("Name") as string;
|
||||
}
|
||||
|
||||
public static string GetSystemVersion() {
|
||||
using var root = Registry.LocalMachine;
|
||||
using var sub = root.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
|
||||
var majorVersion = sub?.GetValue("CurrentMajorVersionNumber");
|
||||
if (majorVersion != null) {
|
||||
var minorVersion = sub?.GetValue("CurrentMinorVersionNumber", "0");
|
||||
var buildNumber = sub?.GetValue("CurrentBuildNumber", "0");
|
||||
return $"{majorVersion}.{minorVersion}.{buildNumber}";
|
||||
} else {
|
||||
var version = sub?.GetValue("CurrentVersion", "0.0");
|
||||
var buildNumber = sub?.GetValue("CurrentBuild", "0");
|
||||
return $"{version}.{buildNumber}";
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetSystemBuild() {
|
||||
using var root = Registry.LocalMachine;
|
||||
using var sub = root.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
|
||||
return (int) (sub?.GetValue("UBR") ?? 0);
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static string GetDeviceID() {
|
||||
using var sdk = Registry.CurrentUser.OpenSubKey("SOFTWARE\\miHoYoSDK");
|
||||
if (sdk?.GetValue("MIHOYOSDK_DEVICE_ID") is not string id) {
|
||||
id = $"{Random.Shared.NextInt64().ToString().SHA1Hash().ToLower()}{DateTimeOffset.Now.ToUnixTimeMilliseconds()}";
|
||||
sdk?.SetValue("MIHOYOSDK_DEVICE_ID", id);
|
||||
}
|
||||
id = id.MD5Hash().ToLower();
|
||||
return $"{id[..8]}-{id[8..12]}-{id[12..16]}-{id[16..20]}-{id[20..]}";
|
||||
}
|
||||
}
|
||||
#pragma warning restore CA1416
|
||||
@@ -1,25 +0,0 @@
|
||||
using YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK;
|
||||
|
||||
public static class ErrorLogHelper {
|
||||
public static MException CreateModelExceptionAndBinaries(Exception exception) {
|
||||
var modelException = new MException {
|
||||
Type = exception.GetType().ToString(),
|
||||
Message = exception.Message,
|
||||
StackTrace = exception.StackTrace
|
||||
};
|
||||
if (exception is AggregateException aggregateException) {
|
||||
if (aggregateException.InnerExceptions.Count != 0) {
|
||||
modelException.InnerExceptions = new List<MException>();
|
||||
foreach (var innerException in aggregateException.InnerExceptions) {
|
||||
modelException.InnerExceptions.Add(CreateModelExceptionAndBinaries(innerException));
|
||||
}
|
||||
}
|
||||
} else if (exception.InnerException != null) {
|
||||
modelException.InnerExceptions ??= new List<MException>();
|
||||
modelException.InnerExceptions.Add(CreateModelExceptionAndBinaries(exception.InnerException));
|
||||
}
|
||||
return modelException;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
public class Device {
|
||||
|
||||
public string SdkName { get; set; } = "appcenter.wpf.netcore";
|
||||
|
||||
public string SdkVersion { get; set; } = "4.5.0";
|
||||
|
||||
public string OsName { get; set; } = "WINDOWS";
|
||||
|
||||
public string OsVersion { get; set; } = DeviceHelper.GetSystemVersion();
|
||||
|
||||
public string OsBuild { get; set; } = $"{DeviceHelper.GetSystemVersion()}.{DeviceHelper.GetSystemBuild()}";
|
||||
|
||||
public string? Model { get; set; } = DeviceHelper.GetModel();
|
||||
|
||||
public string? OemName { get; set; } = DeviceHelper.GetOem();
|
||||
|
||||
public string ScreenSize { get; set; } = DeviceHelper.GetScreenSize();
|
||||
|
||||
public string CarrierCountry { get; set; } = DeviceHelper.GetCountry() ?? "CN";
|
||||
|
||||
public string Locale { get; set; } = CultureInfo.CurrentCulture.Name;
|
||||
|
||||
public int TimeZoneOffset { get; set; } = (int) TimeZoneInfo.Local.BaseUtcOffset.TotalMinutes;
|
||||
|
||||
public string AppVersion { get; set; } = GlobalVars.AppVersionName;
|
||||
|
||||
public string AppBuild { get; set; } = GlobalVars.AppVersionCode.ToString();
|
||||
|
||||
public string AppNamespace { get; set; } = Assembly.GetEntryAssembly()?.EntryPoint?.DeclaringType?.Namespace ?? string.Empty;
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using YaeAchievement.AppCenterSDK.Models.Serialization;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
[LogId(JsonIdentifier)]
|
||||
public class EventLog(string name) : LogWithProperties {
|
||||
|
||||
public const string JsonIdentifier = "event";
|
||||
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
public string Name { get; set; } = name;
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using YaeAchievement.AppCenterSDK.Models.Serialization;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
[LogId(JsonIdentifier)]
|
||||
public class HandledErrorLog : LogWithProperties {
|
||||
|
||||
public const string JsonIdentifier = "handledError";
|
||||
|
||||
public HandledErrorLog(MException exception) {
|
||||
Id = Guid.NewGuid();
|
||||
Exception = exception;
|
||||
}
|
||||
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
public MException Exception { get; set; }
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
public abstract class Log {
|
||||
|
||||
[JsonPropertyName("sid")]
|
||||
public Guid? Session { get; set; } = AppCenter.SessionID;
|
||||
|
||||
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public Device Device { get; set; } = AppCenter.DeviceInfo;
|
||||
|
||||
[JsonIgnore]
|
||||
internal LogStatus Status = LogStatus.Pending;
|
||||
|
||||
}
|
||||
|
||||
public enum LogStatus {
|
||||
Pending, Uploading, Uploaded
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
public class LogContainer {
|
||||
|
||||
public LogContainer(IEnumerable<Log> logs) {
|
||||
Logs = logs;
|
||||
}
|
||||
|
||||
public IEnumerable<Log> Logs { get; set; }
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
public class LogUploadResult {
|
||||
|
||||
public string Status { get; set; } = null!;
|
||||
|
||||
public Guid[] ValidDiagnosticsIds { get; set; } = Array.Empty<Guid>();
|
||||
|
||||
public Guid[] ThrottledDiagnosticsIds { get; set; } = Array.Empty<Guid>();
|
||||
|
||||
public Guid CorrelationId { get; set; }
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
public class LogWithProperties : Log {
|
||||
|
||||
public IDictionary<string, string> Properties { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
public class MException {
|
||||
|
||||
public string Type { get; set; } = "UnknownType";
|
||||
|
||||
public string? Message { get; set; }
|
||||
|
||||
public string? StackTrace { get; set; }
|
||||
|
||||
public IList<StackFrame>? Frames { get; set; }
|
||||
|
||||
public IList<MException>? InnerExceptions { get; set; }
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using YaeAchievement.AppCenterSDK.Models.Serialization;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
[LogId(JsonIdentifier)]
|
||||
public class ManagedErrorLog : Log {
|
||||
|
||||
public const string JsonIdentifier = "managedError";
|
||||
|
||||
public ManagedErrorLog(
|
||||
Exception exception,
|
||||
bool fatal = true
|
||||
) {
|
||||
var p = Process.GetCurrentProcess();
|
||||
Id = Guid.NewGuid();
|
||||
Fatal = fatal;
|
||||
UserId = AppCenter.DeviceID;
|
||||
ProcessId = p.Id;
|
||||
Exception = ErrorLogHelper.CreateModelExceptionAndBinaries(exception);
|
||||
ProcessName = p.ProcessName;
|
||||
Architecture = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
|
||||
AppLaunchTimestamp = p.StartTime.ToUniversalTime();
|
||||
}
|
||||
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public string? UserId { get; set; }
|
||||
|
||||
public int ProcessId { get; set; }
|
||||
|
||||
public string ProcessName { get; set; }
|
||||
|
||||
public bool Fatal { get; set; }
|
||||
|
||||
public DateTime? AppLaunchTimestamp { get; set; }
|
||||
|
||||
public string? Architecture { get; set; }
|
||||
|
||||
public MException Exception { get; set; }
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using YaeAchievement.AppCenterSDK.Models.Serialization;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
[LogId(JsonIdentifier)]
|
||||
public class PageLog : LogWithProperties {
|
||||
|
||||
public const string JsonIdentifier = "page";
|
||||
|
||||
public PageLog(string name) {
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace YaeAchievement.AppCenterSDK.Models.Serialization;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class LogIdAttribute(string id) : Attribute {
|
||||
|
||||
public string Id { get; } = id;
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK.Models.Serialization;
|
||||
|
||||
public class GuidConverter : JsonConverter<Guid> {
|
||||
|
||||
public static GuidConverter Instance { get; } = new ();
|
||||
|
||||
public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options) {
|
||||
writer.WriteStringValue(value.ToString("D"));
|
||||
}
|
||||
}
|
||||
|
||||
public class LogJsonConverter : JsonConverter<Log> {
|
||||
|
||||
public static LogJsonConverter Instance { get; } = new ();
|
||||
|
||||
private static readonly JsonSerializerOptions SerializationSettings;
|
||||
|
||||
static LogJsonConverter() {
|
||||
SerializationSettings = new JsonSerializerOptions {
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
ReferenceHandler = ReferenceHandler.IgnoreCycles,
|
||||
};
|
||||
}
|
||||
|
||||
public override bool CanConvert(Type objectType) => typeof(Log).IsAssignableFrom(objectType);
|
||||
|
||||
public override Log Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Log value, JsonSerializerOptions options) {
|
||||
var attr = value.GetType().GetCustomAttribute<LogIdAttribute>();
|
||||
if (attr == null) {
|
||||
throw new JsonException("Log type is missing LogTypeAttribute");
|
||||
}
|
||||
var cNode = JsonSerializer.SerializeToNode((object) value, SerializationSettings)!;
|
||||
cNode["type"] = attr.Id;
|
||||
writer.WriteRawValue(cNode.ToString());
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK.Models.Serialization;
|
||||
|
||||
public static class LogSerializer {
|
||||
|
||||
private static readonly JsonSerializerOptions SerializationSettings;
|
||||
|
||||
static LogSerializer() {
|
||||
SerializationSettings = new JsonSerializerOptions {
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
ReferenceHandler = ReferenceHandler.IgnoreCycles,
|
||||
Converters = {
|
||||
GuidConverter.Instance,
|
||||
LogJsonConverter.Instance,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static string Serialize(LogContainer logContainer) {
|
||||
return JsonSerializer.Serialize(logContainer, SerializationSettings);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
public class StackFrame {
|
||||
|
||||
public StackFrame(string address, string code, string className, string methodName, int? lineNumber, string fileName) {
|
||||
Address = address;
|
||||
Code = code;
|
||||
ClassName = className;
|
||||
MethodName = methodName;
|
||||
LineNumber = lineNumber;
|
||||
FileName = fileName;
|
||||
}
|
||||
|
||||
public string Address { get; set; }
|
||||
|
||||
public string Code { get; set; }
|
||||
|
||||
public string ClassName { get; set; }
|
||||
|
||||
public string MethodName { get; set; }
|
||||
|
||||
public int? LineNumber { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using YaeAchievement.AppCenterSDK.Models.Serialization;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
[LogId(JsonIdentifier)]
|
||||
public class StartServiceLog : Log {
|
||||
|
||||
public const string JsonIdentifier = "startService";
|
||||
|
||||
public StartServiceLog(params string[] services) {
|
||||
Services = services;
|
||||
}
|
||||
|
||||
public string[] Services { get; set; }
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
using YaeAchievement.AppCenterSDK.Models.Serialization;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK.Models;
|
||||
|
||||
[LogId(JsonIdentifier)]
|
||||
public class StartSessionLog : Log {
|
||||
public const string JsonIdentifier = "startSession";
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using YaeAchievement.res;
|
||||
|
||||
namespace YaeAchievement;
|
||||
|
||||
public static class AppConfig {
|
||||
public static partial class AppConfig {
|
||||
|
||||
public static string GamePath { get; private set; } = null!;
|
||||
|
||||
@@ -52,11 +52,15 @@ public static class AppConfig {
|
||||
try {
|
||||
File.Delete(copiedLogFilePath);
|
||||
} catch (Exception) { /* ignore */}
|
||||
var matchResult = Regex.Match(content, @"(?m).:/.+(GenshinImpact_Data|YuanShen_Data)");
|
||||
var matchResult = GamePathRegex().Match(content);
|
||||
if (!matchResult.Success) {
|
||||
return null;
|
||||
}
|
||||
var entryName = matchResult.Groups["1"].Value.Replace("_Data", ".exe");
|
||||
return Path.GetFullPath(Path.Combine(matchResult.Value, "..", entryName));
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"(?m).:/.+(GenshinImpact_Data|YuanShen_Data)")]
|
||||
private static partial Regex GamePathRegex();
|
||||
|
||||
}
|
||||
|
||||
@@ -4,17 +4,13 @@ using Proto;
|
||||
|
||||
namespace YaeAchievement;
|
||||
|
||||
public class CacheFile {
|
||||
public class CacheFile(string identifier) {
|
||||
|
||||
private readonly string _cacheName;
|
||||
private readonly string _cacheName = Path.Combine(GlobalVars.CachePath, $"{identifier.MD5Hash()[..16]}.miko");
|
||||
private CacheItem? _content;
|
||||
|
||||
public DateTime LastWriteTime => Exists() ? File.GetLastWriteTimeUtc(_cacheName) : DateTime.UnixEpoch;
|
||||
|
||||
public CacheFile(string identifier) {
|
||||
_cacheName = Path.Combine(GlobalVars.CachePath, $"{identifier.MD5Hash()[..16]}.miko");
|
||||
}
|
||||
|
||||
public bool Exists() => File.Exists(_cacheName);
|
||||
|
||||
public CacheItem Read() {
|
||||
|
||||
@@ -6,7 +6,6 @@ using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Win32;
|
||||
using Proto;
|
||||
using YaeAchievement.AppCenterSDK;
|
||||
using YaeAchievement.res;
|
||||
using static Proto.Achievement.Types;
|
||||
|
||||
@@ -16,6 +15,10 @@ public static class Export {
|
||||
|
||||
public static uint ExportTo { get; set; } = uint.MaxValue;
|
||||
|
||||
private static readonly JsonSerializerOptions JsonOpts = new () {
|
||||
WriteIndented = true
|
||||
};
|
||||
|
||||
public static void Choose(AchievementAllDataNotify data) {
|
||||
if (ExportTo == uint.MaxValue) {
|
||||
Console.Write(App.ExportChoose);
|
||||
@@ -40,16 +43,15 @@ public static class Export {
|
||||
}
|
||||
|
||||
private class CocogoatResponse {
|
||||
[JsonPropertyName("key")] public string Code { get; set; } = null!;
|
||||
[JsonPropertyName("key")] public string Code { get; init; } = null!;
|
||||
}
|
||||
|
||||
private static void ToCocogoat(AchievementAllDataNotify data) {
|
||||
var result = JsonSerializer.Serialize(ExportToUIAFApp(data));
|
||||
using var request = new HttpRequestMessage {
|
||||
Method = HttpMethod.Post,
|
||||
RequestUri = new Uri($"https://77.cocogoat.cn/v1/memo?source={App.AllAchievement}"),
|
||||
Content = new StringContent(result, Encoding.UTF8, "application/json")
|
||||
};
|
||||
using var request = new HttpRequestMessage();
|
||||
request.Method = HttpMethod.Post;
|
||||
request.RequestUri = new Uri($"https://77.cocogoat.cn/v1/memo?source={App.AllAchievement}");
|
||||
request.Content = new StringContent(result, Encoding.UTF8, "application/json");
|
||||
using var response = Utils.CHttpClient.Send(request);
|
||||
if (response.StatusCode != HttpStatusCode.Created) {
|
||||
Console.WriteLine(App.ExportToCocogoatFail);
|
||||
@@ -68,11 +70,10 @@ public static class Export {
|
||||
{ "key", id },
|
||||
{ "data", ExportToUIAFApp(data) }
|
||||
});
|
||||
using var request = new HttpRequestMessage {
|
||||
Method = HttpMethod.Post,
|
||||
RequestUri = new Uri("https://api.qyinter.com/achievementRedis"),
|
||||
Content = new StringContent(result, Encoding.UTF8, "application/json")
|
||||
};
|
||||
using var request = new HttpRequestMessage();
|
||||
request.Method = HttpMethod.Post;
|
||||
request.RequestUri = new Uri("https://api.qyinter.com/achievementRedis");
|
||||
request.Content = new StringContent(result, Encoding.UTF8, "application/json");
|
||||
using var response = Utils.CHttpClient.Send(request);
|
||||
Console.WriteLine(App.ExportToWxApp1Success, id);
|
||||
}
|
||||
@@ -100,7 +101,7 @@ public static class Export {
|
||||
}
|
||||
|
||||
private static void ToTeyvatGuide(AchievementAllDataNotify data) {
|
||||
if (Process.GetProcessesByName("TeyvatGuide").Any()) {
|
||||
if (Process.GetProcessesByName("TeyvatGuide").Length != 0) {
|
||||
Utils.CopyToClipboard(JsonSerializer.Serialize(ExportToUIAFApp(data)));
|
||||
Utils.ShellOpen("teyvatguide://import_uigf?app=YaeAchievement");
|
||||
Console.WriteLine(App.ExportToTauriSuccess);
|
||||
@@ -171,10 +172,10 @@ public static class Export {
|
||||
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;
|
||||
outList.Add(new List<object> {
|
||||
ach.Id, ach.Status.ToDesc(), achInfo.Group, achInfo.Name,
|
||||
outList.Add([
|
||||
ach.Id, ach.Status.ToDesc(), achInfo.Group, achInfo.Name,
|
||||
achInfo.Description, current, ach.Total, finishAt
|
||||
});
|
||||
]);
|
||||
}
|
||||
var output = new List<string> { "ID,状态,特辑,名称,描述,当前进度,目标进度,完成时间" };
|
||||
output.AddRange(outList.OrderBy(v => v[2]).Select(item => {
|
||||
@@ -190,9 +191,7 @@ public static class Export {
|
||||
|
||||
private static void ToRawJson(AchievementAllDataNotify data) {
|
||||
var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-raw.json");
|
||||
var text = JsonSerializer.Serialize(data, new JsonSerializerOptions {
|
||||
WriteIndented = true
|
||||
});
|
||||
var text = JsonSerializer.Serialize(data, JsonOpts);
|
||||
if (TryWriteToFile(path, text)) {
|
||||
Console.WriteLine(App.ExportToFileSuccess, path);
|
||||
}
|
||||
@@ -220,6 +219,7 @@ public static class Export {
|
||||
};
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private static bool CheckWinUIAppScheme(string protocol) {
|
||||
return (string?)Registry.ClassesRoot.OpenSubKey(protocol)?.GetValue("") == $"URL:{protocol}";
|
||||
}
|
||||
@@ -228,7 +228,7 @@ public static class Export {
|
||||
return string.Join(separator, list);
|
||||
}
|
||||
|
||||
private static readonly List<uint> UnusedAchievement = new() { 84517 };
|
||||
private static readonly List<uint> UnusedAchievement = [ 84517 ];
|
||||
|
||||
private static string ToDesc(this Status status) {
|
||||
return status switch {
|
||||
@@ -248,7 +248,6 @@ public static class Export {
|
||||
public static int PrintMsgAndReturnErrCode(this Win32Exception ex, string msg) {
|
||||
// ReSharper disable once LocalizableElement
|
||||
Console.WriteLine($"{msg}: {ex.Message}");
|
||||
AppCenter.TrackCrash(ex, false);
|
||||
return ex.NativeErrorCode;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using Proto;
|
||||
using YaeAchievement;
|
||||
using YaeAchievement.AppCenterSDK;
|
||||
using YaeAchievement.AppCenterSDK.Models;
|
||||
using YaeAchievement.res;
|
||||
using static YaeAchievement.Utils;
|
||||
|
||||
@@ -22,13 +20,6 @@ AppConfig.Load(args.GetOrNull(0) ?? "auto");
|
||||
Export.ExportTo = ToUIntOrNull(args.GetOrNull(1)) ?? uint.MaxValue;
|
||||
|
||||
CheckUpdate(ToBooleanOrFalse(args.GetOrNull(2)));
|
||||
AppCenter.Init();
|
||||
new EventLog("AppInit") {
|
||||
Properties = {
|
||||
{ "AppVersion", GlobalVars.AppVersionName },
|
||||
{ "SystemVersion", DeviceHelper.GetSystemVersion() }
|
||||
}
|
||||
}.Enqueue();
|
||||
|
||||
var historyCache = new CacheFile("ExportData");
|
||||
|
||||
|
||||
26
src/Utils.cs
26
src/Utils.cs
@@ -11,7 +11,6 @@ using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.System.Console;
|
||||
using Proto;
|
||||
using YaeAchievement.AppCenterSDK;
|
||||
using YaeAchievement.res;
|
||||
|
||||
namespace YaeAchievement;
|
||||
@@ -31,10 +30,9 @@ public static class Utils {
|
||||
|
||||
public static byte[] GetBucketFileAsByteArray(string path, bool cache = true) {
|
||||
try {
|
||||
using var msg = new HttpRequestMessage {
|
||||
Method = HttpMethod.Get,
|
||||
RequestUri = new Uri($"{GlobalVars.BucketHost}/{path}")
|
||||
};
|
||||
using var msg = new HttpRequestMessage();
|
||||
msg.Method = HttpMethod.Get;
|
||||
msg.RequestUri = new Uri($"{GlobalVars.BucketHost}/{path}");
|
||||
var cacheFile = new CacheFile(path);
|
||||
if (cache && cacheFile.Exists()) {
|
||||
msg.Headers.TryAddWithoutValidation("If-None-Match", $"{cacheFile.Read().Etag}");
|
||||
@@ -73,11 +71,11 @@ public static class Utils {
|
||||
if (Native.OpenClipboard(HWND.Null))
|
||||
{
|
||||
Native.EmptyClipboard();
|
||||
var hGlobal = (HANDLE) Marshal.AllocHGlobal((text.Length + 1) * 2);
|
||||
var hGlobal = (HGLOBAL) Marshal.AllocHGlobal((text.Length + 1) * 2);
|
||||
var hPtr = (nint) Native.GlobalLock(hGlobal);
|
||||
Marshal.Copy(text.ToCharArray(), 0, hPtr, text.Length);
|
||||
Native.GlobalUnlock(hPtr);
|
||||
Native.SetClipboardData(13, hGlobal);
|
||||
Native.GlobalUnlock((HGLOBAL) hPtr);
|
||||
Native.SetClipboardData(13, new HANDLE(hPtr));
|
||||
Marshal.FreeHGlobal(hGlobal);
|
||||
Native.CloseClipboard();
|
||||
}
|
||||
@@ -201,9 +199,6 @@ public static class Utils {
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine(ex.ToString());
|
||||
Console.WriteLine(App.UploadError);
|
||||
AppCenter.TrackCrash((Exception) e.ExceptionObject);
|
||||
AppCenter.Upload();
|
||||
break;
|
||||
}
|
||||
Environment.Exit(-1);
|
||||
@@ -312,12 +307,9 @@ public static class Utils {
|
||||
}
|
||||
await File.WriteAllBytesAsync(pkgPath, bytes);
|
||||
Console.WriteLine(App.VcRuntimeInstalling);
|
||||
using var process = new Process {
|
||||
StartInfo = {
|
||||
FileName = pkgPath,
|
||||
Arguments = "/install /passive /norestart"
|
||||
}
|
||||
};
|
||||
using var process = new Process();
|
||||
process.StartInfo.FileName = pkgPath;
|
||||
process.StartInfo.Arguments = "/install /passive /norestart";
|
||||
process.Start();
|
||||
await process.WaitForExitAsync();
|
||||
File.Delete(pkgPath);
|
||||
|
||||
Reference in New Issue
Block a user