From a5fcfca609f3b99b6dc69893e3e0e3b8804d5848 Mon Sep 17 00:00:00 2001 From: Xhichn Date: Wed, 19 Apr 2023 13:18:01 +0800 Subject: [PATCH 1/3] Feat: Daily check-in support for hoyolab user --- .../Snap.Hutao/Core/CoreEnvironment.cs | 2 +- .../View/Dialog/AdoptCalculatorDialog.xaml.cs | 8 +-- .../Dialog/CommunityGameRecordDialog.xaml.cs | 8 +-- .../DailyNoteVerificationDialog.xaml.cs | 2 +- .../View/Dialog/SignInWebViewDialog.xaml.cs | 8 +-- .../Web/Bridge/CoreWebView2Extension.cs | 13 ++-- .../Web/Bridge/MiHoYoJSInterface.cs | 63 ++++++++++++++++--- .../Web/Bridge/SignInJsInterface.cs | 6 +- 8 files changed, 80 insertions(+), 30 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs b/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs index 01cdabf7..f4d292c7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/CoreEnvironment.cs @@ -47,7 +47,7 @@ internal static class CoreEnvironment /// /// Hoyolab Rpc 版本 /// - public const string HoyolabOsXrpcVersion = "2.28.0"; + public const string HoyolabOsXrpcVersion = "2.30.0"; /// /// 盐 diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/AdoptCalculatorDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/AdoptCalculatorDialog.xaml.cs index 0b8cf797..c1fddf64 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/AdoptCalculatorDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/AdoptCalculatorDialog.xaml.cs @@ -11,7 +11,7 @@ using Snap.Hutao.Web.Bridge; namespace Snap.Hutao.View.Dialog; /// -/// ɼԻ +/// 养成计算器对话框 /// [HighQuality] internal sealed partial class AdoptCalculatorDialog : ContentDialog @@ -20,9 +20,9 @@ internal sealed partial class AdoptCalculatorDialog : ContentDialog private MiHoYoJSInterface? jsInterface; /// - /// һµɼԻ + /// 构造一个新的养成计算器对话框 /// - /// + /// 窗体 public AdoptCalculatorDialog() { InitializeComponent(); @@ -49,7 +49,7 @@ internal sealed partial class AdoptCalculatorDialog : ContentDialog } coreWebView2.SetCookie(user.CookieToken, user.LToken, null).SetMobileUserAgent(); - jsInterface = new(coreWebView2, scope.ServiceProvider); + jsInterface = new(coreWebView2, scope.ServiceProvider, false); jsInterface.ClosePageRequested += OnClosePageRequested; coreWebView2.Navigate($"http://webstatic.mihoyo.com/ys/event/e20200923adopt_calculator/index.html?bbs_presentation_style=fullscreen&bbs_auth_required=true&&utm_source=bbs&utm_medium=mys&utm_campaign=GameRecord"); diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/CommunityGameRecordDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/CommunityGameRecordDialog.xaml.cs index 7d19c987..b8981412 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/CommunityGameRecordDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/CommunityGameRecordDialog.xaml.cs @@ -11,7 +11,7 @@ using Snap.Hutao.Web.Bridge; namespace Snap.Hutao.View.Dialog; /// -/// Ϸ¼Ի +/// 社区游戏记录对话框 /// [HighQuality] internal sealed partial class CommunityGameRecordDialog : ContentDialog @@ -20,9 +20,9 @@ internal sealed partial class CommunityGameRecordDialog : ContentDialog private MiHoYoJSInterface? jsInterface; /// - /// һµϷ¼Ի + /// 构造一个新的社区游戏记录对话框 /// - /// + /// 窗体 public CommunityGameRecordDialog() { InitializeComponent(); @@ -47,7 +47,7 @@ internal sealed partial class CommunityGameRecordDialog : ContentDialog } coreWebView2.SetCookie(user.CookieToken, user.LToken, null).SetMobileUserAgent(); - jsInterface = new(coreWebView2, scope.ServiceProvider); + jsInterface = new(coreWebView2, scope.ServiceProvider, false); jsInterface.ClosePageRequested += OnClosePageRequested; coreWebView2.Navigate("https://webstatic.mihoyo.com/app/community-game-records/index.html"); diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteVerificationDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteVerificationDialog.xaml.cs index 02e2e4c3..6f9cc1eb 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteVerificationDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteVerificationDialog.xaml.cs @@ -45,7 +45,7 @@ internal sealed partial class DailyNoteVerificationDialog : ContentDialog Model.Entity.User user = userAndUid.User; coreWebView2.SetCookie(user.CookieToken, user.LToken, null).SetMobileUserAgent(); - jsInterface = new(coreWebView2, scope.ServiceProvider); + jsInterface = new(coreWebView2, scope.ServiceProvider, false); jsInterface.ClosePageRequested += OnClosePageRequested; string query = $"?role_id={userAndUid.Uid.Value}&server={userAndUid.Uid.Region}"; diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs index 8c66590b..db978b6b 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs @@ -48,14 +48,14 @@ internal sealed partial class SignInWebViewDialog : ContentDialog if (user.Entity.IsOversea) { - coreWebView2.SetCookie(user.CookieToken, user.LToken, null).SetMobileOverseaUserAgent(); - signInJsInterface = new(coreWebView2, scope.ServiceProvider); + coreWebView2.SetCookie(user.CookieToken, user.LToken, null, true).SetMobileOverseaUserAgent(); + signInJsInterface = new(coreWebView2, scope.ServiceProvider, true); coreWebView2.Navigate("https://act.hoyolab.com/ys/event/signin-sea-v3/index.html?act_id=e202102251931481"); } else { - coreWebView2.SetCookie(user.CookieToken, user.LToken, null).SetMobileUserAgent(); - signInJsInterface = new(coreWebView2, scope.ServiceProvider); + coreWebView2.SetCookie(user.CookieToken, user.LToken, null, false).SetMobileUserAgent(); + signInJsInterface = new(coreWebView2, scope.ServiceProvider, false); coreWebView2.Navigate("https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?act_id=e202009291139501"); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs index be4030ee..9afb559e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs @@ -41,32 +41,33 @@ internal static class CoreWebView2Extension /// CookieToken /// LToken /// SToken + /// 是否为国际服,用于改变 cookie domain /// 链式调用的WebView2 - public static CoreWebView2 SetCookie(this CoreWebView2 webView, Cookie? cookieToken = null, Cookie? lToken = null, Cookie? sToken = null) + public static CoreWebView2 SetCookie(this CoreWebView2 webView, Cookie? cookieToken = null, Cookie? lToken = null, Cookie? sToken = null, bool isOversea = false) { CoreWebView2CookieManager cookieManager = webView.CookieManager; if (cookieToken != null) { - cookieManager.AddMihoyoCookie("account_id", cookieToken).AddMihoyoCookie("cookie_token", cookieToken); + cookieManager.AddMihoyoCookie("account_id", cookieToken, isOversea).AddMihoyoCookie("cookie_token", cookieToken, isOversea); } if (lToken != null) { - cookieManager.AddMihoyoCookie("ltuid", lToken).AddMihoyoCookie("ltoken", lToken); + cookieManager.AddMihoyoCookie("ltuid", lToken, isOversea).AddMihoyoCookie("ltoken", lToken, isOversea); } if (sToken != null) { - cookieManager.AddMihoyoCookie("stuid", sToken).AddMihoyoCookie("stoken", sToken); + cookieManager.AddMihoyoCookie("stuid", sToken, isOversea).AddMihoyoCookie("stoken", sToken, isOversea); } return webView; } - private static CoreWebView2CookieManager AddMihoyoCookie(this CoreWebView2CookieManager manager, string name, Cookie cookie) + private static CoreWebView2CookieManager AddMihoyoCookie(this CoreWebView2CookieManager manager, string name, Cookie cookie, bool isOversea = false) { - manager.AddOrUpdateCookie(manager.CreateCookie(name, cookie[name], ".mihoyo.com", "/")); + manager.AddOrUpdateCookie(manager.CreateCookie(name, cookie[name], isOversea ? ".hoyolab.com" : ".mihoyo.com", "/")); return manager; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs index bd34ac6a..0722bce1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs @@ -9,6 +9,7 @@ using Snap.Hutao.Web.Hoyolab; using Snap.Hutao.Web.Hoyolab.Bbs.User; using Snap.Hutao.Web.Hoyolab.DynamicSecret; using Snap.Hutao.Web.Hoyolab.Takumi.Auth; +using System.Globalization; using System.Runtime.InteropServices; using System.Text; @@ -35,6 +36,11 @@ internal class MiHoYoJSInterface document.querySelector('body').appendChild(st); """; + private const string RemoveRotationWarningScript = """ + let landscape = document.getElementById('mihoyo_landscape'); + landscape.remove(); + """; + private readonly CoreWebView2 webView; private readonly IServiceProvider serviceProvider; private readonly ILogger logger; @@ -45,10 +51,12 @@ internal class MiHoYoJSInterface /// /// webview2 /// 服务提供器 - public MiHoYoJSInterface(CoreWebView2 webView, IServiceProvider serviceProvider) + /// 是否为 HoYoVerse 账号 + public MiHoYoJSInterface(CoreWebView2 webView, IServiceProvider serviceProvider, bool isOversea) { this.webView = webView; this.serviceProvider = serviceProvider; + IsOversea = isOversea; logger = serviceProvider.GetRequiredService>(); @@ -57,8 +65,14 @@ internal class MiHoYoJSInterface webView.NavigationStarting += OnNavigationStarting; } + public event Action? ClosePageRequested; + /// + /// 是否为 HoYoVerse 账号 + /// + public bool IsOversea { get; private set; } + /// /// 获取ActionTicket /// @@ -67,10 +81,20 @@ internal class MiHoYoJSInterface public virtual async Task GetActionTicketAsync(JsParam jsParam) { User user = serviceProvider.GetRequiredService().Current!; - return await serviceProvider - .GetRequiredService() - .GetActionTicketBySTokenAsync(jsParam.Payload!.ActionType, user.Entity) - .ConfigureAwait(false); + + if (IsOversea) + { + // TODO: ActionTicket for hoyolab account + return null; + } + else + { + return await serviceProvider + .GetRequiredService() + .GetActionTicketBySTokenAsync(jsParam.Payload!.ActionType, user.Entity) + .ConfigureAwait(false); + } + } /// @@ -86,7 +110,7 @@ internal class MiHoYoJSInterface { { "x-rpc-client_type", "5" }, { "x-rpc-device_id", Core.CoreEnvironment.HoyolabDeviceId }, - { "x-rpc-app_version", Core.CoreEnvironment.HoyolabXrpcVersion }, + { "x-rpc-app_version", IsOversea ? Core.CoreEnvironment.HoyolabOsXrpcVersion : Core.CoreEnvironment.HoyolabXrpcVersion }, }, }; } @@ -148,6 +172,7 @@ internal class MiHoYoJSInterface /// 响应 public virtual JsResult> GetDynamicSecrectV2(JsParam param) { + // TODO: Salt X4 for hoyolab user string salt = Core.CoreEnvironment.DynamicSecretSalts[SaltType.X4]; long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); int r = GetRandom(); @@ -253,6 +278,23 @@ internal class MiHoYoJSInterface return null; } + /// + /// 获取当前语言和时区 + /// + /// param + /// 语言与时区 + public virtual JsResult> GetCurrentLocale(JsParam param) + { + return new() + { + Data = new() + { + ["language"] = CultureInfo.CurrentUICulture.Name, + ["timeZone"] = "GMT+8", + }, + }; + } + public virtual Task ShowAlertDialogAsync(JsParam param) { return Task.FromException(new NotImplementedException()); @@ -378,6 +420,7 @@ internal class MiHoYoJSInterface "login" => null, "pushPage" => await PushPageAsync(param).ConfigureAwait(false), "showLoading" => null, + "getCurrentLocale" => GetCurrentLocale(param), _ => LogUnhandledMessage("Unhandled Message Type: {method}", param.Method), }; } @@ -391,11 +434,17 @@ internal class MiHoYoJSInterface private void OnDOMContentLoaded(CoreWebView2 coreWebView2, CoreWebView2DOMContentLoadedEventArgs args) { coreWebView2.ExecuteScriptAsync(HideScrollBarScript).AsTask().SafeForget(logger); + + // 移除“请旋转手机”提示所在的HTML元素 + if (IsOversea) + { + coreWebView2.ExecuteScriptAsync(RemoveRotationWarningScript).AsTask().SafeForget(logger); + } } private void OnNavigationStarting(CoreWebView2 coreWebView2, CoreWebView2NavigationStartingEventArgs args) { - if (new Uri(args.Uri).Host.EndsWith("mihoyo.com")) + if (new Uri(args.Uri).Host.EndsWith(IsOversea ? "hoyolab.com" : "mihoyo.com")) { // Execute this solve issue: When open same site second time,there might be no bridge init. coreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(InitializeJsInterfaceScript2).AsTask().SafeForget(logger); diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJsInterface.cs b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJsInterface.cs index cd8a9fe4..b4bb28a2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJsInterface.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJsInterface.cs @@ -13,8 +13,8 @@ namespace Snap.Hutao.Web.Bridge; internal sealed class SignInJsInterface : MiHoYoJSInterface { /// - public SignInJsInterface(CoreWebView2 webView, IServiceProvider serviceProvider) - : base(webView, serviceProvider) + public SignInJsInterface(CoreWebView2 webView, IServiceProvider serviceProvider, bool isOversea) + : base(webView, serviceProvider, isOversea) { } @@ -27,7 +27,7 @@ internal sealed class SignInJsInterface : MiHoYoJSInterface { { "x-rpc-client_type", "2" }, { "x-rpc-device_id", Core.CoreEnvironment.HoyolabDeviceId }, - { "x-rpc-app_version", Core.CoreEnvironment.HoyolabXrpcVersion }, + { "x-rpc-app_version", IsOversea ? Core.CoreEnvironment.HoyolabOsXrpcVersion : Core.CoreEnvironment.HoyolabXrpcVersion }, }, }; } From b5371a965698d2d5a3a519a0ed39145f1a235a67 Mon Sep 17 00:00:00 2001 From: Xhichn Date: Wed, 19 Apr 2023 18:23:45 +0800 Subject: [PATCH 2/3] Use seperated js interface for hoyolab check-in --- .../View/Dialog/AdoptCalculatorDialog.xaml.cs | 2 +- .../Dialog/CommunityGameRecordDialog.xaml.cs | 2 +- .../DailyNoteVerificationDialog.xaml.cs | 2 +- .../View/Dialog/SignInWebViewDialog.xaml.cs | 6 +-- .../Web/Bridge/MiHoYoJSInterface.cs | 47 ++++--------------- .../Web/Bridge/SignInJSInterfaceOversea.cs | 46 ++++++++++++++++++ .../Web/Bridge/SignInJsInterface.cs | 6 +-- 7 files changed, 65 insertions(+), 46 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJSInterfaceOversea.cs diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/AdoptCalculatorDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/AdoptCalculatorDialog.xaml.cs index c1fddf64..fc74e5be 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/AdoptCalculatorDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/AdoptCalculatorDialog.xaml.cs @@ -49,7 +49,7 @@ internal sealed partial class AdoptCalculatorDialog : ContentDialog } coreWebView2.SetCookie(user.CookieToken, user.LToken, null).SetMobileUserAgent(); - jsInterface = new(coreWebView2, scope.ServiceProvider, false); + jsInterface = new(coreWebView2, scope.ServiceProvider); jsInterface.ClosePageRequested += OnClosePageRequested; coreWebView2.Navigate($"http://webstatic.mihoyo.com/ys/event/e20200923adopt_calculator/index.html?bbs_presentation_style=fullscreen&bbs_auth_required=true&&utm_source=bbs&utm_medium=mys&utm_campaign=GameRecord"); diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/CommunityGameRecordDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/CommunityGameRecordDialog.xaml.cs index b8981412..4fe97297 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/CommunityGameRecordDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/CommunityGameRecordDialog.xaml.cs @@ -47,7 +47,7 @@ internal sealed partial class CommunityGameRecordDialog : ContentDialog } coreWebView2.SetCookie(user.CookieToken, user.LToken, null).SetMobileUserAgent(); - jsInterface = new(coreWebView2, scope.ServiceProvider, false); + jsInterface = new(coreWebView2, scope.ServiceProvider); jsInterface.ClosePageRequested += OnClosePageRequested; coreWebView2.Navigate("https://webstatic.mihoyo.com/app/community-game-records/index.html"); diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteVerificationDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteVerificationDialog.xaml.cs index 6f9cc1eb..02e2e4c3 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteVerificationDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteVerificationDialog.xaml.cs @@ -45,7 +45,7 @@ internal sealed partial class DailyNoteVerificationDialog : ContentDialog Model.Entity.User user = userAndUid.User; coreWebView2.SetCookie(user.CookieToken, user.LToken, null).SetMobileUserAgent(); - jsInterface = new(coreWebView2, scope.ServiceProvider, false); + jsInterface = new(coreWebView2, scope.ServiceProvider); jsInterface.ClosePageRequested += OnClosePageRequested; string query = $"?role_id={userAndUid.Uid.Value}&server={userAndUid.Uid.Region}"; diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs index db978b6b..74a2c5a7 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs @@ -17,7 +17,7 @@ internal sealed partial class SignInWebViewDialog : ContentDialog { private readonly IServiceScope scope; [SuppressMessage("", "IDE0052")] - private SignInJsInterface? signInJsInterface; + private MiHoYoJSInterface? signInJsInterface; /// /// 构造一个新的签到网页视图对话框 @@ -49,13 +49,13 @@ internal sealed partial class SignInWebViewDialog : ContentDialog if (user.Entity.IsOversea) { coreWebView2.SetCookie(user.CookieToken, user.LToken, null, true).SetMobileOverseaUserAgent(); - signInJsInterface = new(coreWebView2, scope.ServiceProvider, true); + signInJsInterface = new SignInJSInterfaceOversea(coreWebView2, scope.ServiceProvider); coreWebView2.Navigate("https://act.hoyolab.com/ys/event/signin-sea-v3/index.html?act_id=e202102251931481"); } else { coreWebView2.SetCookie(user.CookieToken, user.LToken, null, false).SetMobileUserAgent(); - signInJsInterface = new(coreWebView2, scope.ServiceProvider, false); + signInJsInterface = new SignInJsInterface(coreWebView2, scope.ServiceProvider); coreWebView2.Navigate("https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?act_id=e202009291139501"); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs index 0722bce1..23cc30a1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs @@ -36,11 +36,6 @@ internal class MiHoYoJSInterface document.querySelector('body').appendChild(st); """; - private const string RemoveRotationWarningScript = """ - let landscape = document.getElementById('mihoyo_landscape'); - landscape.remove(); - """; - private readonly CoreWebView2 webView; private readonly IServiceProvider serviceProvider; private readonly ILogger logger; @@ -51,12 +46,10 @@ internal class MiHoYoJSInterface /// /// webview2 /// 服务提供器 - /// 是否为 HoYoVerse 账号 - public MiHoYoJSInterface(CoreWebView2 webView, IServiceProvider serviceProvider, bool isOversea) + public MiHoYoJSInterface(CoreWebView2 webView, IServiceProvider serviceProvider) { this.webView = webView; this.serviceProvider = serviceProvider; - IsOversea = isOversea; logger = serviceProvider.GetRequiredService>(); @@ -65,14 +58,8 @@ internal class MiHoYoJSInterface webView.NavigationStarting += OnNavigationStarting; } - public event Action? ClosePageRequested; - /// - /// 是否为 HoYoVerse 账号 - /// - public bool IsOversea { get; private set; } - /// /// 获取ActionTicket /// @@ -81,20 +68,10 @@ internal class MiHoYoJSInterface public virtual async Task GetActionTicketAsync(JsParam jsParam) { User user = serviceProvider.GetRequiredService().Current!; - - if (IsOversea) - { - // TODO: ActionTicket for hoyolab account - return null; - } - else - { - return await serviceProvider - .GetRequiredService() - .GetActionTicketBySTokenAsync(jsParam.Payload!.ActionType, user.Entity) - .ConfigureAwait(false); - } - + return await serviceProvider + .GetRequiredService() + .GetActionTicketBySTokenAsync(jsParam.Payload!.ActionType, user.Entity) + .ConfigureAwait(false); } /// @@ -110,7 +87,7 @@ internal class MiHoYoJSInterface { { "x-rpc-client_type", "5" }, { "x-rpc-device_id", Core.CoreEnvironment.HoyolabDeviceId }, - { "x-rpc-app_version", IsOversea ? Core.CoreEnvironment.HoyolabOsXrpcVersion : Core.CoreEnvironment.HoyolabXrpcVersion }, + { "x-rpc-app_version", Core.CoreEnvironment.HoyolabXrpcVersion }, }, }; } @@ -285,11 +262,12 @@ internal class MiHoYoJSInterface /// 语言与时区 public virtual JsResult> GetCurrentLocale(JsParam param) { + string cultureName = CultureInfo.CurrentCulture.Name; return new() { Data = new() { - ["language"] = CultureInfo.CurrentUICulture.Name, + ["language"] = cultureName.ToLowerInvariant(), ["timeZone"] = "GMT+8", }, }; @@ -434,17 +412,12 @@ internal class MiHoYoJSInterface private void OnDOMContentLoaded(CoreWebView2 coreWebView2, CoreWebView2DOMContentLoadedEventArgs args) { coreWebView2.ExecuteScriptAsync(HideScrollBarScript).AsTask().SafeForget(logger); - - // 移除“请旋转手机”提示所在的HTML元素 - if (IsOversea) - { - coreWebView2.ExecuteScriptAsync(RemoveRotationWarningScript).AsTask().SafeForget(logger); - } } private void OnNavigationStarting(CoreWebView2 coreWebView2, CoreWebView2NavigationStartingEventArgs args) { - if (new Uri(args.Uri).Host.EndsWith(IsOversea ? "hoyolab.com" : "mihoyo.com")) + string uriHost = new Uri(args.Uri).Host; + if (uriHost.EndsWith("mihoyo.com") || uriHost.EndsWith("hoyolab.com")) { // Execute this solve issue: When open same site second time,there might be no bridge init. coreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(InitializeJsInterfaceScript2).AsTask().SafeForget(logger); diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJSInterfaceOversea.cs b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJSInterfaceOversea.cs new file mode 100644 index 00000000..01c9fbba --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJSInterfaceOversea.cs @@ -0,0 +1,46 @@ +using Microsoft.Web.WebView2.Core; +using Snap.Hutao.Web.Bridge.Model; + +namespace Snap.Hutao.Web.Bridge; + +/// +/// HoYoLAB 签到页面JS桥 +/// +[HighQuality] +internal sealed class SignInJSInterfaceOversea : MiHoYoJSInterface +{ + private const string RemoveRotationWarningScript = """ + let landscape = document.getElementById('mihoyo_landscape'); + landscape.remove(); + """; + + private readonly ILogger logger; + + /// + public SignInJSInterfaceOversea(CoreWebView2 webView, IServiceProvider serviceProvider) + : base(webView, serviceProvider) + { + logger = serviceProvider.GetRequiredService>(); + webView.DOMContentLoaded += OnDOMContentLoaded; + } + + /// + public override JsResult> GetHttpRequestHeader(JsParam param) + { + return new() + { + Data = new Dictionary() + { + { "x-rpc-client_type", "2" }, + { "x-rpc-device_id", Core.CoreEnvironment.HoyolabDeviceId }, + { "x-rpc-app_version", Core.CoreEnvironment.HoyolabOsXrpcVersion }, + }, + }; + } + + private void OnDOMContentLoaded(CoreWebView2 coreWebView2, CoreWebView2DOMContentLoadedEventArgs args) + { + // 移除“请旋转手机”提示所在的HTML元素 + coreWebView2.ExecuteScriptAsync(RemoveRotationWarningScript).AsTask().SafeForget(logger); + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJsInterface.cs b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJsInterface.cs index b4bb28a2..cd8a9fe4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJsInterface.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/SignInJsInterface.cs @@ -13,8 +13,8 @@ namespace Snap.Hutao.Web.Bridge; internal sealed class SignInJsInterface : MiHoYoJSInterface { /// - public SignInJsInterface(CoreWebView2 webView, IServiceProvider serviceProvider, bool isOversea) - : base(webView, serviceProvider, isOversea) + public SignInJsInterface(CoreWebView2 webView, IServiceProvider serviceProvider) + : base(webView, serviceProvider) { } @@ -27,7 +27,7 @@ internal sealed class SignInJsInterface : MiHoYoJSInterface { { "x-rpc-client_type", "2" }, { "x-rpc-device_id", Core.CoreEnvironment.HoyolabDeviceId }, - { "x-rpc-app_version", IsOversea ? Core.CoreEnvironment.HoyolabOsXrpcVersion : Core.CoreEnvironment.HoyolabXrpcVersion }, + { "x-rpc-app_version", Core.CoreEnvironment.HoyolabXrpcVersion }, }, }; } From d876f269fd54110d033637f154adf60b6bf0a892 Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Wed, 19 Apr 2023 21:27:35 +0800 Subject: [PATCH 3/3] typo --- src/Snap.Hutao/Snap.Hutao/Program.cs | 9 +++++++-- src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs | 6 ++++++ .../Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs | 9 ++++----- .../Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs | 9 +++++---- .../Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs | 8 +++++--- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Program.cs b/src/Snap.Hutao/Snap.Hutao/Program.cs index 83b59a66..ee3473d1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Program.cs +++ b/src/Snap.Hutao/Snap.Hutao/Program.cs @@ -34,7 +34,7 @@ public static partial class Program // by adding the using statement, we can dispose the injected services when we closing using (ServiceProvider serviceProvider = InitializeDependencyInjection()) { - InitializeCulture(serviceProvider.GetRequiredService().CurrentCulture); + InitializeCulture(serviceProvider); // In a Desktop app this runs a message pump internally, // and does not return until the application shuts down. @@ -49,8 +49,13 @@ public static partial class Program _ = Ioc.Default.GetRequiredService(); } - private static void InitializeCulture(CultureInfo cultureInfo) + private static void InitializeCulture(IServiceProvider serviceProvider) { + AppOptions appOptions = serviceProvider.GetRequiredService(); + appOptions.PreviousCulture = CultureInfo.CurrentCulture; + + CultureInfo cultureInfo = appOptions.CurrentCulture; + CultureInfo.CurrentCulture = cultureInfo; CultureInfo.CurrentUICulture = cultureInfo; ApplicationLanguages.PrimaryLanguageOverride = cultureInfo.Name; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs index 84cbd732..5ceced67 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/AppOptions.cs @@ -55,6 +55,12 @@ internal sealed class AppOptions : DbStoreOptions set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, value => value.ToString()); } + /// + /// 初始化前的语言 + /// 通过设置与获取此属性,就可以获取到与系统同步的语言 + /// + public CultureInfo PreviousCulture { get; set; } = default!; + /// /// 当前语言 /// diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs index 74a2c5a7..11495a9e 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/SignInWebViewDialog.xaml.cs @@ -17,12 +17,11 @@ internal sealed partial class SignInWebViewDialog : ContentDialog { private readonly IServiceScope scope; [SuppressMessage("", "IDE0052")] - private MiHoYoJSInterface? signInJsInterface; + private MiHoYoJSInterface? jsInterface; /// /// 构造一个新的签到网页视图对话框 /// - /// 窗口 public SignInWebViewDialog() { InitializeComponent(); @@ -49,20 +48,20 @@ internal sealed partial class SignInWebViewDialog : ContentDialog if (user.Entity.IsOversea) { coreWebView2.SetCookie(user.CookieToken, user.LToken, null, true).SetMobileOverseaUserAgent(); - signInJsInterface = new SignInJSInterfaceOversea(coreWebView2, scope.ServiceProvider); + jsInterface = new SignInJSInterfaceOversea(coreWebView2, scope.ServiceProvider); coreWebView2.Navigate("https://act.hoyolab.com/ys/event/signin-sea-v3/index.html?act_id=e202102251931481"); } else { coreWebView2.SetCookie(user.CookieToken, user.LToken, null, false).SetMobileUserAgent(); - signInJsInterface = new SignInJsInterface(coreWebView2, scope.ServiceProvider); + jsInterface = new SignInJsInterface(coreWebView2, scope.ServiceProvider); coreWebView2.Navigate("https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?act_id=e202009291139501"); } } private void OnContentDialogClosed(ContentDialog sender, ContentDialogClosedEventArgs args) { - signInJsInterface = null; + jsInterface = null; scope.Dispose(); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs index 9afb559e..4fb6f6e8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs @@ -49,17 +49,17 @@ internal static class CoreWebView2Extension if (cookieToken != null) { - cookieManager.AddMihoyoCookie("account_id", cookieToken, isOversea).AddMihoyoCookie("cookie_token", cookieToken, isOversea); + cookieManager.AddMihoyoCookie(Cookie.ACCOUNT_ID, cookieToken, isOversea).AddMihoyoCookie(Cookie.COOKIE_TOKEN, cookieToken, isOversea); } if (lToken != null) { - cookieManager.AddMihoyoCookie("ltuid", lToken, isOversea).AddMihoyoCookie("ltoken", lToken, isOversea); + cookieManager.AddMihoyoCookie(Cookie.LTUID, lToken, isOversea).AddMihoyoCookie(Cookie.LTOKEN, lToken, isOversea); } if (sToken != null) { - cookieManager.AddMihoyoCookie("stuid", sToken, isOversea).AddMihoyoCookie("stoken", sToken, isOversea); + cookieManager.AddMihoyoCookie(Cookie.STUID, sToken, isOversea).AddMihoyoCookie(Cookie.STOKEN, sToken, isOversea); } return webView; @@ -67,7 +67,8 @@ internal static class CoreWebView2Extension private static CoreWebView2CookieManager AddMihoyoCookie(this CoreWebView2CookieManager manager, string name, Cookie cookie, bool isOversea = false) { - manager.AddOrUpdateCookie(manager.CreateCookie(name, cookie[name], isOversea ? ".hoyolab.com" : ".mihoyo.com", "/")); + string domain = isOversea ? ".hoyolab.com" : ".mihoyo.com"; + manager.AddOrUpdateCookie(manager.CreateCookie(name, cookie[name], domain, "/")); return manager; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs index 23cc30a1..52b35bd0 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/MiHoYoJSInterface.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.Web.WebView2.Core; +using Snap.Hutao.Service; using Snap.Hutao.Service.User; using Snap.Hutao.ViewModel.User; using Snap.Hutao.Web.Bridge.Model; @@ -262,12 +263,13 @@ internal class MiHoYoJSInterface /// 语言与时区 public virtual JsResult> GetCurrentLocale(JsParam param) { - string cultureName = CultureInfo.CurrentCulture.Name; + AppOptions appOptions = serviceProvider.GetRequiredService(); + return new() { Data = new() { - ["language"] = cultureName.ToLowerInvariant(), + ["language"] = appOptions.PreviousCulture.Name.ToLowerInvariant(), ["timeZone"] = "GMT+8", }, }; @@ -389,6 +391,7 @@ internal class MiHoYoJSInterface "getActionTicket" => await GetActionTicketAsync(param).ConfigureAwait(false), "getCookieInfo" => GetCookieInfo(param), "getCookieToken" => await GetCookieTokenAsync(param).ConfigureAwait(false), + "getCurrentLocale" => GetCurrentLocale(param), "getDS" => GetDynamicSecrectV1(param), "getDS2" => GetDynamicSecrectV2(param), "getHTTPRequestHeaders" => GetHttpRequestHeader(param), @@ -398,7 +401,6 @@ internal class MiHoYoJSInterface "login" => null, "pushPage" => await PushPageAsync(param).ConfigureAwait(false), "showLoading" => null, - "getCurrentLocale" => GetCurrentLocale(param), _ => LogUnhandledMessage("Unhandled Message Type: {method}", param.Method), }; }