From 2fb6cd344174861410cce4f54def1bb6f0868452 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Mon, 11 Dec 2023 18:47:41 +0800 Subject: [PATCH] code style (?) --- .../Factory/QrCode/IQrCodeFactory.cs | 2 +- .../Factory/QrCode/QrCodeFactory.cs | 2 +- .../Snap.Hutao/View/Dialog/QrCodeDialog.xaml | 1 - .../View/Dialog/QrCodeDialog.xaml.cs | 71 ++++++++++--------- src/Snap.Hutao/Snap.Hutao/View/UserView.xaml | 2 +- .../ViewModel/User/UserViewModel.cs | 9 ++- src/Snap.Hutao/Snap.Hutao/Web/ApiEndpoints.cs | 15 ++-- .../Web/Hoyolab/Hk4e/QrCode/QrCodeClient.cs | 63 ---------------- .../Hoyolab/Hk4e/QrCode/QrCodeFetchOptions.cs | 20 ------ .../Web/Hoyolab/Hk4e/QrCode/QrCodeQuery.cs | 14 ---- .../Hoyolab/Hk4e/QrCode/QrCodeQueryOptions.cs | 24 ------- .../Hoyolab/Hk4e/QrCode/QrCodeQueryStatus.cs | 14 ---- .../Snap.Hutao/Web/Hoyolab/HoyolabOptions.cs | 5 ++ .../Passport/GameLoginRequestOptions.cs | 26 +++++++ .../GameLoginRequestResult.cs} | 7 +- .../Web/Hoyolab/Passport/GameLoginResult.cs | 21 ++++++ .../Passport/GameLoginResultOptions.cs | 30 ++++++++ .../GameLoginResultPayload.ProtoTypes.cs} | 4 +- .../GameLoginResultPayload.cs} | 5 +- .../Hoyolab/Passport/GameLoginResultStatus.cs | 14 ++++ .../Web/Hoyolab/Passport/PassportClient2.cs | 41 +++++++++++ .../UidGameToken.cs} | 6 +- .../Takumi/Account/SessionAppClient.cs | 7 +- .../Web/Response/KnownReturnCode.cs | 10 +-- 24 files changed, 209 insertions(+), 204 deletions(-) delete mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeClient.cs delete mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeFetchOptions.cs delete mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQuery.cs delete mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryOptions.cs delete mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryStatus.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginRequestOptions.cs rename src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/{Hk4e/QrCode/QrCodeFetch.cs => Passport/GameLoginRequestResult.cs} (56%) create mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResult.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultOptions.cs rename src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/{Hk4e/QrCode/QrCodeQueryPayload.Constant.cs => Passport/GameLoginResultPayload.ProtoTypes.cs} (76%) rename src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/{Hk4e/QrCode/QrCodeQueryPayload.cs => Passport/GameLoginResultPayload.cs} (77%) create mode 100644 src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultStatus.cs rename src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/{Hk4e/QrCode/QrCodeAccount.cs => Passport/UidGameToken.cs} (63%) diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/QrCode/IQrCodeFactory.cs b/src/Snap.Hutao/Snap.Hutao/Factory/QrCode/IQrCodeFactory.cs index 3381dc01..0ab732fa 100644 --- a/src/Snap.Hutao/Snap.Hutao/Factory/QrCode/IQrCodeFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Factory/QrCode/IQrCodeFactory.cs @@ -5,5 +5,5 @@ namespace Snap.Hutao.Factory.QrCode; internal interface IQrCodeFactory { - byte[] CreateByteArr(string source); + byte[] CreateQrCodeByteArray(string source); } diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/QrCode/QrCodeFactory.cs b/src/Snap.Hutao/Snap.Hutao/Factory/QrCode/QrCodeFactory.cs index b16d0d29..4ee567fc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Factory/QrCode/QrCodeFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Factory/QrCode/QrCodeFactory.cs @@ -9,7 +9,7 @@ namespace Snap.Hutao.Factory.QrCode; [Injection(InjectAs.Singleton, typeof(IQrCodeFactory))] internal class QrCodeFactory : IQrCodeFactory { - public byte[] CreateByteArr(string source) + public byte[] CreateQrCodeByteArray(string source) { using (QRCodeGenerator generator = new()) { diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/QrCodeDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/QrCodeDialog.xaml index bc8e44cb..177a814c 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/QrCodeDialog.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/QrCodeDialog.xaml @@ -5,7 +5,6 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:shcm="using:Snap.Hutao.Control.Markup" - xmlns:shvd="using:Snap.Hutao.View.Dialog" Title="{shcm:ResourceString Name=ViewDialogQrCodeTitle}" CloseButtonText="{shcm:ResourceString Name=ContentDialogCancelCloseButtonText}" DefaultButton="Close" diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/QrCodeDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/QrCodeDialog.xaml.cs index e14bf962..235f766b 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/QrCodeDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/QrCodeDialog.xaml.cs @@ -3,10 +3,10 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Media.Imaging; using Snap.Hutao.Factory.QrCode; using Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; +using Snap.Hutao.Web.Hoyolab.Passport; using Snap.Hutao.Web.Response; using System.IO; using System.Text.RegularExpressions; @@ -20,10 +20,10 @@ namespace Snap.Hutao.View.Dialog; internal sealed partial class QrCodeDialog : ContentDialog { private readonly ITaskContext taskContext; - private readonly QrCodeClient qrCodeClient; + private readonly PassportClient2 passportClient2; private readonly IQrCodeFactory qrCodeFactory; - private QrCodeAccount? account; + private UidGameToken? account; /// /// 构造一个新的扫描二维码对话框 @@ -34,26 +34,27 @@ internal sealed partial class QrCodeDialog : ContentDialog InitializeComponent(); taskContext = serviceProvider.GetRequiredService(); - qrCodeClient = serviceProvider.GetRequiredService(); + passportClient2 = serviceProvider.GetRequiredService(); qrCodeFactory = serviceProvider.GetRequiredService(); - Initialize().SafeForget(); + FetchQrCodeAsync().SafeForget(); } /// /// 获取登录的用户 /// /// QrCodeAccount - public async ValueTask> GetAccountAsync() + [SuppressMessage("", "SH007")] + public async ValueTask> GetAccountAsync() { await taskContext.SwitchToMainThreadAsync(); ContentDialogResult result = await ShowAsync(); return new(account is not null, account!); } - private async ValueTask Initialize() + private async ValueTask FetchQrCodeAsync() { - Response fetch = await qrCodeClient.PostQrCodeFetchAsync().ConfigureAwait(false); + Response fetch = await passportClient2.PostQrCodeFetchAsync().ConfigureAwait(false); if (fetch.IsOk()) { string url = Regex.Unescape(fetch.Data.Url); @@ -61,7 +62,7 @@ internal sealed partial class QrCodeDialog : ContentDialog await taskContext.SwitchToMainThreadAsync(); BitmapImage bitmap = new(); - await bitmap.SetSourceAsync(new MemoryStream(qrCodeFactory.CreateByteArr(url)).AsRandomAccessStream()); + await bitmap.SetSourceAsync(new MemoryStream(qrCodeFactory.CreateQrCodeByteArray(url)).AsRandomAccessStream()); ImageView.Source = bitmap; if (bitmap is BitmapSource { PixelHeight: > 0, PixelWidth: > 0 }) @@ -70,37 +71,41 @@ internal sealed partial class QrCodeDialog : ContentDialog } await taskContext.SwitchToBackgroundAsync(); + await CheckStatusAsync(ticket).ConfigureAwait(false); + } + } - using (PeriodicTimer timer = new(TimeSpan.FromSeconds(3))) + private async ValueTask CheckStatusAsync(string ticket) + { + using (PeriodicTimer timer = new(TimeSpan.FromSeconds(3))) + { + while (await timer.WaitForNextTickAsync().ConfigureAwait(false)) { - while (await timer.WaitForNextTickAsync().ConfigureAwait(false)) + Response query = await passportClient2.PostQrCodeQueryAsync(ticket).ConfigureAwait(false); + if (query.IsOk(false)) { - Response query = await qrCodeClient.PostQrCodeQueryAsync(ticket).ConfigureAwait(false); - if (query.IsOk(false)) + switch (query.Data.Stat) { - switch (query.Data.Stat) - { - case QrCodeQueryStatus.INIT: - case QrCodeQueryStatus.SCANNED: - break; // @switch - case QrCodeQueryStatus.CONFIRMED: - if (query.Data.Payload.Proto == QrCodeQueryPayload.ACCOUNT) - { - account = JsonSerializer.Deserialize(query.Data.Payload.Raw); - await taskContext.SwitchToMainThreadAsync(); - Hide(); - return; - } + case GameLoginResultStatus.Init: + case GameLoginResultStatus.Scanned: + break; // @switch + case GameLoginResultStatus.Confirmed: + if (query.Data.Payload.Proto == GameLoginResultPayload.ACCOUNT) + { + account = JsonSerializer.Deserialize(query.Data.Payload.Raw); + await taskContext.SwitchToMainThreadAsync(); + Hide(); + return; // Stop timer + } - break; // @switch - } - } - else if (query.ReturnCode == (int)KnownReturnCode.QrCodeExpired) - { - Initialize().SafeForget(); - break; // @while + break; // @switch } } + else if (query.ReturnCode == (int)KnownReturnCode.QrCodeExpired) + { + FetchQrCodeAsync().SafeForget(); + break; // @while + } } } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml b/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml index fe59a7b2..d58233b3 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml @@ -158,7 +158,7 @@ Width="{StaticResource LargeAppBarButtonWidth}" MaxWidth="{StaticResource LargeAppBarButtonWidth}" Margin="2,-4" - Command="{Binding LoginQrCodeCommand}" + Command="{Binding LoginByQrCodeCommand}" Icon="{shcm:FontIcon Glyph={StaticResource FontIconContentQrCode}}" Label="{shcm:ResourceString Name=ViewUserCookieOperationLoginQrCodeAction}"/> ().ConfigureAwait(false); - ValueResult result = await dialog.GetAccountAsync().ConfigureAwait(false); + ValueResult result = await dialog.GetAccountAsync().ConfigureAwait(false); - if (result.TryGetValue(out QrCodeAccount account)) + if (result.TryGetValue(out UidGameToken account)) { Response gameTokenResp = await sessionAppClient.PostSTokenByGameTokenAsync(account).ConfigureAwait(false); diff --git a/src/Snap.Hutao/Snap.Hutao/Web/ApiEndpoints.cs b/src/Snap.Hutao/Snap.Hutao/Web/ApiEndpoints.cs index e19db0fc..95032e1f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/ApiEndpoints.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/ApiEndpoints.cs @@ -16,15 +16,6 @@ namespace Snap.Hutao.Web; [SuppressMessage("", "SA1124")] internal static class ApiEndpoints { - #region ApiTakumiAccountSessionApp - - /// - /// 通过 GameToken 获取 SToken (V2) - /// - public const string STokenByGameToken = $"{ApiTakumiAccountSessionApp}/getTokenByGameToken"; - - #endregion - #region ApiTakumiAuthApi /// @@ -304,6 +295,11 @@ internal static class ApiEndpoints /// public const string AccountGetLTokenBySToken = $"{PassportApiAuthApi}/getLTokenBySToken"; + /// + /// 通过GameToken获取V2SToken + /// + public const string AccountGetSTokenByGameToken = $"{PassportApi}/account/ma-cn-session/app/getTokenByGameToken"; + /// /// 获取V2SToken /// @@ -378,7 +374,6 @@ internal static class ApiEndpoints #region Hosts | Queries private const string ApiTakumi = "https://api-takumi.mihoyo.com"; private const string ApiTakumiAuthApi = $"{ApiTakumi}/auth/api"; - private const string ApiTakumiAccountSessionApp = $"{ApiTakumi}/account/ma-cn-session/app"; private const string ApiTaKumiBindingApi = $"{ApiTakumi}/binding/api"; private const string ApiTakumiCardApi = $"{ApiTakumiRecord}/game_record/app/card/api"; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeClient.cs deleted file mode 100644 index 7c5d5020..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeClient.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; -using Snap.Hutao.Web.Request.Builder; -using Snap.Hutao.Web.Request.Builder.Abstraction; -using Snap.Hutao.Web.Response; -using System.Net.Http; - -namespace Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; - -[HighQuality] -[ConstructorGenerated(ResolveHttpClient = true)] -[HttpClient(HttpClientConfiguration.Default)] -internal sealed partial class QrCodeClient -{ - private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory; - private readonly ILogger logger; - private readonly HttpClient httpClient; - - private readonly string device = Core.Random.GetLetterAndNumberString(64); - - /// - /// 异步获取扫码链接 - /// - /// 取消令牌 - /// login url - public async ValueTask> PostQrCodeFetchAsync(CancellationToken token = default) - { - QrCodeFetchOptions options = new(4, device); - - HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create() - .SetRequestUri(ApiEndpoints.QrCodeFetch) - .PostJson(options); - - Response? resp = await builder - .TryCatchSendAsync>(httpClient, logger, token) - .ConfigureAwait(false); - - return Response.Response.DefaultIfNull(resp); - } - - /// - /// 异步获取扫码状态 - /// - /// 扫码链接中的ticket - /// 取消令牌/param> - /// 扫码状态 - public async ValueTask> PostQrCodeQueryAsync(string ticket, CancellationToken token = default) - { - QrCodeQueryOptions options = new(4, device, ticket); - - HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create() - .SetRequestUri(ApiEndpoints.QrCodeQuery) - .PostJson(options); - - Response? resp = await builder - .TryCatchSendAsync>(httpClient, logger, token) - .ConfigureAwait(false); - - return Response.Response.DefaultIfNull(resp); - } -} diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeFetchOptions.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeFetchOptions.cs deleted file mode 100644 index df689141..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeFetchOptions.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -namespace Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; - -[HighQuality] -internal sealed class QrCodeFetchOptions -{ - public QrCodeFetchOptions(int appId, string device) - { - AppId = appId; - Device = device; - } - - [JsonPropertyName("app_id")] - public int AppId { get; set; } - - [JsonPropertyName("device")] - public string Device { get; set; } = default!; -} diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQuery.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQuery.cs deleted file mode 100644 index 3091ec4e..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQuery.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -namespace Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; - -[HighQuality] -internal sealed class QrCodeQuery -{ - [JsonPropertyName("stat")] - public string Stat { get; set; } = default!; - - [JsonPropertyName("payload")] - public QrCodeQueryPayload Payload { get; set; } = default!; -} diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryOptions.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryOptions.cs deleted file mode 100644 index 9f2806d8..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryOptions.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -namespace Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; - -[HighQuality] -internal sealed class QrCodeQueryOptions -{ - public QrCodeQueryOptions(int appId, string device, string ticket) - { - AppId = appId; - Device = device; - Ticket = ticket; - } - - [JsonPropertyName("app_id")] - public int AppId { get; set; } - - [JsonPropertyName("device")] - public string Device { get; set; } = default!; - - [JsonPropertyName("ticket")] - public string Ticket { get; set; } = default!; -} diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryStatus.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryStatus.cs deleted file mode 100644 index ce0e9813..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryStatus.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -namespace Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; - -/// -/// 扫码状态 -/// -internal sealed partial class QrCodeQueryStatus -{ - public const string INIT = "Init"; - public const string SCANNED = "Scanned"; - public const string CONFIRMED = "Confirmed"; -} diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabOptions.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabOptions.cs index f5e391a6..4610b2c9 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabOptions.cs @@ -37,6 +37,11 @@ internal sealed class HoyolabOptions : IOptions /// public static string DeviceId { get; } = Guid.NewGuid().ToString(); + /// + /// 扫码登录设备Id + /// + public static string Device { get; } = Core.Random.GetLetterAndNumberString(64); + /// /// 盐 /// diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginRequestOptions.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginRequestOptions.cs new file mode 100644 index 00000000..fb3b77a4 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginRequestOptions.cs @@ -0,0 +1,26 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Web.Hoyolab.Passport; + +/// +/// 扫码登录请求配置 +/// +[HighQuality] +internal sealed class GameLoginRequestOptions +{ + [JsonPropertyName("app_id")] + public int AppId { get; set; } + + [JsonPropertyName("device")] + public string Device { get; set; } = default!; + + public static GameLoginRequestOptions Create(int appId, string device) + { + return new GameLoginRequestOptions + { + AppId = appId, + Device = device, + }; + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeFetch.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginRequestResult.cs similarity index 56% rename from src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeFetch.cs rename to src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginRequestResult.cs index bac70add..13f067b2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeFetch.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginRequestResult.cs @@ -1,10 +1,13 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -namespace Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; +namespace Snap.Hutao.Web.Hoyolab.Passport; +/// +/// 扫码登录请求结果 +/// [HighQuality] -internal sealed class QrCodeFetch +internal sealed class GameLoginRequestResult { [JsonPropertyName("url")] public string Url { get; set; } = default!; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResult.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResult.cs new file mode 100644 index 00000000..c3757f69 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResult.cs @@ -0,0 +1,21 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Core.Json.Annotation; +using Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; + +namespace Snap.Hutao.Web.Hoyolab.Passport; + +/// +/// 扫码登录结果 +/// +[HighQuality] +internal sealed class GameLoginResult +{ + [JsonPropertyName("stat")] + [JsonEnum(JsonSerializeType.String)] + public GameLoginResultStatus Stat { get; set; } = default!; + + [JsonPropertyName("payload")] + public GameLoginResultPayload Payload { get; set; } = default!; +} diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultOptions.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultOptions.cs new file mode 100644 index 00000000..d5f17cd6 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultOptions.cs @@ -0,0 +1,30 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Web.Hoyolab.Passport; + +/// +/// 扫码登录结果请求配置 +/// +[HighQuality] +internal sealed class GameLoginResultOptions +{ + [JsonPropertyName("app_id")] + public int AppId { get; set; } + + [JsonPropertyName("device")] + public string Device { get; set; } = default!; + + [JsonPropertyName("ticket")] + public string Ticket { get; set; } = default!; + + public static GameLoginResultOptions Create(int appId, string device, string ticket) + { + return new GameLoginResultOptions + { + AppId = appId, + Device = device, + Ticket = ticket, + }; + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryPayload.Constant.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultPayload.ProtoTypes.cs similarity index 76% rename from src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryPayload.Constant.cs rename to src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultPayload.ProtoTypes.cs index d71edfd4..179b7501 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryPayload.Constant.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultPayload.ProtoTypes.cs @@ -4,9 +4,9 @@ namespace Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; /// -/// Proto 常量 +/// Proto 类型常量 /// -internal sealed partial class QrCodeQueryPayload +internal sealed partial class GameLoginResultPayload { public const string ACCOUNT = "Account"; public const string RAW = "Raw"; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryPayload.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultPayload.cs similarity index 77% rename from src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryPayload.cs rename to src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultPayload.cs index e66b64ba..8d7cd653 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeQueryPayload.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultPayload.cs @@ -3,8 +3,11 @@ namespace Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; +/// +/// 扫码登录结果Payload +/// [HighQuality] -internal sealed partial class QrCodeQueryPayload +internal sealed partial class GameLoginResultPayload { [JsonPropertyName("proto")] public string Proto { get; set; } = default!; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultStatus.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultStatus.cs new file mode 100644 index 00000000..9f95988f --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/GameLoginResultStatus.cs @@ -0,0 +1,14 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Web.Hoyolab.Passport; + +/// +/// 扫码状态 +/// +internal enum GameLoginResultStatus +{ + Init, + Scanned, + Confirmed, +} diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/PassportClient2.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/PassportClient2.cs index f6e3713f..be261a77 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/PassportClient2.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/PassportClient2.cs @@ -68,6 +68,47 @@ internal sealed partial class PassportClient2 return Response.Response.DefaultIfNull(resp); } + /// + /// 异步获取扫码链接 + /// + /// 取消令牌 + /// 二维码原始链接 + public async ValueTask> PostQrCodeFetchAsync(CancellationToken token = default) + { + GameLoginRequestOptions options = GameLoginRequestOptions.Create(4, HoyolabOptions.Device); + + HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create() + .SetRequestUri(ApiEndpoints.QrCodeFetch) + .PostJson(options); + + Response? resp = await builder + .TryCatchSendAsync>(httpClient, logger, token) + .ConfigureAwait(false); + + return Response.Response.DefaultIfNull(resp); + } + + /// + /// 异步获取扫码状态 + /// + /// 扫码链接中的ticket + /// 取消令牌 + /// 扫码结果 + public async ValueTask> PostQrCodeQueryAsync(string ticket, CancellationToken token = default) + { + GameLoginResultOptions options = GameLoginResultOptions.Create(4, HoyolabOptions.Device, ticket); + + HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create() + .SetRequestUri(ApiEndpoints.QrCodeQuery) + .PostJson(options); + + Response? resp = await builder + .TryCatchSendAsync>(httpClient, logger, token) + .ConfigureAwait(false); + + return Response.Response.DefaultIfNull(resp); + } + private class Timestamp { [JsonPropertyName("t")] diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeAccount.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/UidGameToken.cs similarity index 63% rename from src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeAccount.cs rename to src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/UidGameToken.cs index 9c48cd45..7f2ffc47 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/QrCode/QrCodeAccount.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/UidGameToken.cs @@ -1,13 +1,13 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -namespace Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; +namespace Snap.Hutao.Web.Hoyolab.Passport; [HighQuality] -internal sealed class QrCodeAccount +internal sealed class UidGameToken { [JsonPropertyName("uid")] - public string Stuid { get; set; } = default!; + public string Uid { get; set; } = default!; [JsonPropertyName("token")] public string GameToken { get; set; } = default!; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Account/SessionAppClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Account/SessionAppClient.cs index 6cd5b0bf..57f1c63d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Account/SessionAppClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Account/SessionAppClient.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; -using Snap.Hutao.Web.Hoyolab.Hk4e.QrCode; using Snap.Hutao.Web.Hoyolab.Passport; using Snap.Hutao.Web.Request.Builder; using Snap.Hutao.Web.Request.Builder.Abstraction; @@ -27,16 +26,16 @@ internal sealed partial class SessionAppClient /// 扫码获得的账户信息 /// 取消令牌 /// 登录结果 - public async ValueTask> PostSTokenByGameTokenAsync(QrCodeAccount account, CancellationToken token = default) + public async ValueTask> PostSTokenByGameTokenAsync(UidGameToken account, CancellationToken token = default) { GameTokenWrapper wrapper = new() { - Stuid = int.Parse(account.Stuid, CultureInfo.CurrentCulture), + Stuid = int.Parse(account.Uid, CultureInfo.CurrentCulture), GameToken = account.GameToken, }; HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create() - .SetRequestUri(ApiEndpoints.STokenByGameToken) + .SetRequestUri(ApiEndpoints.AccountGetSTokenByGameToken) .PostJson(wrapper); Response? resp = await builder diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Response/KnownReturnCode.cs b/src/Snap.Hutao/Snap.Hutao/Web/Response/KnownReturnCode.cs index d1f701b1..5725680a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Response/KnownReturnCode.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Response/KnownReturnCode.cs @@ -84,6 +84,11 @@ internal enum KnownReturnCode /// AppIdError = -109, + /// + /// 二维码已过期 + /// + QrCodeExpired = -106, + /// /// 验证密钥过期 /// @@ -138,9 +143,4 @@ internal enum KnownReturnCode /// 实时便笺 /// CODE10104 = 10104, - - /// - /// 二维码已过期 - /// - QrCodeExpired = -106, }