diff --git a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest
index 4a4c007a..97bf087f 100644
--- a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest
+++ b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest
@@ -12,7 +12,7 @@
+ Version="1.6.0.0" />
Snap Hutao
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs b/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs
index 80def9f0..ed4dee16 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs
@@ -194,7 +194,7 @@ internal class UserService : IUserService
public async Task> ProcessInputCookieAsync(Cookie cookie, bool isOversea)
{
await ThreadHelper.SwitchToBackgroundAsync();
- string? mid = cookie.GetValueOrDefault(isOversea ? Cookie.MID : Cookie.STUID);
+ string? mid = cookie.GetValueOrDefault(isOversea ? Cookie.STUID : Cookie.MID);
if (mid == null)
{
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml
index a33a6337..04029e3a 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml
@@ -21,7 +21,12 @@
VerticalAlignment="Top"
PlaceholderText="{shcm:ResourceString Name=ViewDialogUserInputPlaceholder}"
TextChanged="InputTextChanged"/>
-
+
+
+ 0
+ 0
+ 0
+
-
-
-
-
-
-
-
-
-
-
+ Click="CookieButtonClick"
+ Content="{shcm:ResourceString Name=ViewPageLoginMihoyoUserLoggedInAction}"/>
+
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/LoginHoyoverseUserPage.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Page/LoginHoyoverseUserPage.xaml.cs
index e220dc0e..a1e03385 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/LoginHoyoverseUserPage.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/LoginHoyoverseUserPage.xaml.cs
@@ -6,9 +6,12 @@ using Microsoft.Web.WebView2.Core;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.Navigation;
using Snap.Hutao.Service.User;
+using Snap.Hutao.Web;
using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.Takumi.Auth;
+using Snap.Hutao.Web.Request;
using Snap.Hutao.Web.Response;
+using System.Net.Http;
namespace Snap.Hutao.View.Page;
@@ -25,6 +28,26 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
InitializeComponent();
}
+ private static async Task GetUidFromCookieAsync(IServiceProvider serviceProvider, Cookie cookie, CancellationToken token = default)
+ {
+ JsonSerializerOptions options = serviceProvider.GetRequiredService();
+ ILogger logger = serviceProvider.GetRequiredService>();
+ HttpClient httpClient = serviceProvider.GetRequiredService();
+
+ httpClient.DefaultRequestHeaders.Set("Cookie", cookie.ToString());
+
+ WebApiResponse? resp = await httpClient
+ .TryCatchGetFromJsonAsync>(ApiOsEndpoints.WebApiOsAccountLoginByCookie, options, logger, token)
+ .ConfigureAwait(false);
+
+ if (resp != null)
+ {
+ return resp.Data.AccountInfo.AccountId.ToString();
+ }
+
+ return string.Empty;
+ }
+
[SuppressMessage("", "VSTHRD100")]
private async void OnRootLoaded(object sender, RoutedEventArgs e)
{
@@ -54,17 +77,8 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
IInfoBarService infoBarService = Ioc.Default.GetRequiredService();
- // Get user id from text input, login_uid is missed in cookie
- string uid = UidInputText.Text;
-
- if (uid.Length != 9)
- {
- await ThreadHelper.SwitchToMainThreadAsync();
- infoBarService.Information(SH.ViewPageLoginHoyoverseUserHint);
- return;
- }
-
Cookie loginTicketCookie = Cookie.FromCoreWebView2Cookies(cookies);
+ string uid = await GetUidFromCookieAsync(Ioc.Default, loginTicketCookie, token).ConfigureAwait(false);
loginTicketCookie[Cookie.LOGIN_UID] = uid;
// 使用 loginTicket 获取 stoken
@@ -89,34 +103,71 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
Ioc.Default.GetRequiredService().GoBack();
- switch (result)
- {
- case UserOptionResult.Added:
- ViewModel.User.UserViewModel vm = Ioc.Default.GetRequiredService();
- if (vm.Users!.Count == 1)
- {
- await ThreadHelper.SwitchToMainThreadAsync();
- vm.SelectedUser = vm.Users.Single();
- }
-
- infoBarService.Success(string.Format(SH.ViewModelUserAdded, nickname));
- break;
- case UserOptionResult.Incomplete:
- infoBarService.Information(SH.ViewModelUserIncomplete);
- break;
- case UserOptionResult.Invalid:
- infoBarService.Information(SH.ViewModelUserInvalid);
- break;
- case UserOptionResult.Updated:
- infoBarService.Success(string.Format(SH.ViewModelUserUpdated, nickname));
- break;
- default:
- throw Must.NeverHappen();
- }
+ await Ioc.Default
+ .GetRequiredService()
+ .HandleUserOptionResultAsync(result, nickname)
+ .ConfigureAwait(false);
}
private void CookieButtonClick(object sender, RoutedEventArgs e)
{
HandleCurrentCookieAsync().SafeForget();
}
+
+ private sealed class WebApiResponse
+ {
+ [JsonPropertyName("code")]
+ public int Code { get; set; }
+
+ [JsonPropertyName("data")]
+ public TData Data { get; set; } = default!;
+ }
+
+ private sealed class AccountInfoWrapper
+ {
+ [JsonPropertyName("account_info")]
+ public AccountInfo AccountInfo { get; set; } = default!;
+
+ [JsonPropertyName("game_ctrl_info")]
+ public JsonElement GameControlInfo { get; set; }
+
+ [JsonPropertyName("info")]
+ public string Info { get; set; } = default!;
+
+ [JsonPropertyName("msg")]
+ public string Message { get; set; } = default!;
+
+ [JsonPropertyName("notice_info")]
+ public JsonElement NoticeInfo { get; set; }
+
+ [JsonPropertyName("status")]
+ public int Status { get; set; }
+ }
+
+ private sealed class AccountInfo
+ {
+ [JsonPropertyName("account_id")]
+ public int AccountId { get; set; }
+
+ [JsonPropertyName("account_name")]
+ public string AccountName { get; set; } = default!;
+
+ [JsonPropertyName("area_code")]
+ public string AreaCode { get; set; } = default!;
+
+ [JsonPropertyName("country")]
+ public string Country { get; set; } = default!;
+
+ [JsonPropertyName("email")]
+ public string Email { get; set; } = default!;
+
+ [JsonPropertyName("mobile")]
+ public string Mobile { get; set; } = default!;
+
+ [JsonPropertyName("safe_level")]
+ public int SafeLevel { get; set; }
+
+ [JsonPropertyName("weblogin_token")]
+ public string WebLoginToken { get; set; } = default!;
+ }
}
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml
index 7e118eb3..13489497 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml
@@ -23,9 +23,6 @@
HorizontalAlignment="Right"
Click="CookieButtonClick"
Content="{shcm:ResourceString Name=ViewPageLoginMihoyoUserLoggedInAction}"/>
-
+
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml.cs
index 921d09aa..fec041db 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/LoginMihoyoUserPage.xaml.cs
@@ -86,33 +86,11 @@ internal sealed partial class LoginMihoyoUserPage : Microsoft.UI.Xaml.Controls.P
.ConfigureAwait(false);
Ioc.Default.GetRequiredService().GoBack();
- IInfoBarService infoBarService = Ioc.Default.GetRequiredService();
- // TODO: Move these code somewhere else.
- switch (result)
- {
- case UserOptionResult.Added:
- ViewModel.User.UserViewModel vm = Ioc.Default.GetRequiredService();
- if (vm.Users!.Count == 1)
- {
- await ThreadHelper.SwitchToMainThreadAsync();
- vm.SelectedUser = vm.Users.Single();
- }
-
- infoBarService.Success(string.Format(SH.ViewModelUserAdded, nickname));
- break;
- case UserOptionResult.Incomplete:
- infoBarService.Information(SH.ViewModelUserIncomplete);
- break;
- case UserOptionResult.Invalid:
- infoBarService.Information(SH.ViewModelUserInvalid);
- break;
- case UserOptionResult.Updated:
- infoBarService.Success(string.Format(SH.ViewModelUserUpdated, nickname));
- break;
- default:
- throw Must.NeverHappen();
- }
+ await Ioc.Default
+ .GetRequiredService()
+ .HandleUserOptionResultAsync(result, nickname)
+ .ConfigureAwait(false);
}
private void CookieButtonClick(object sender, RoutedEventArgs e)
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs
index be07f75f..48e6c629 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs
@@ -117,6 +117,39 @@ internal sealed class UserViewModel : ObservableObject
///
public ICommand RefreshCookieTokenCommand { get; }
+ ///
+ /// 处理用户操作结果
+ ///
+ /// 操作结果
+ /// uid
+ /// 任务
+ public async Task HandleUserOptionResultAsync(UserOptionResult optionResult, string uid)
+ {
+ switch (optionResult)
+ {
+ case UserOptionResult.Added:
+ if (Users!.Count == 1)
+ {
+ await ThreadHelper.SwitchToMainThreadAsync();
+ SelectedUser = Users.Single();
+ }
+
+ infoBarService.Success(string.Format(SH.ViewModelUserAdded, uid));
+ break;
+ case UserOptionResult.Incomplete:
+ infoBarService.Information(SH.ViewModelUserIncomplete);
+ break;
+ case UserOptionResult.Invalid:
+ infoBarService.Information(SH.ViewModelUserInvalid);
+ break;
+ case UserOptionResult.Updated:
+ infoBarService.Success(string.Format(SH.ViewModelUserUpdated, uid));
+ break;
+ default:
+ throw Must.NeverHappen();
+ }
+ }
+
private async Task OpenUIAsync()
{
try
@@ -155,29 +188,7 @@ internal sealed class UserViewModel : ObservableObject
(UserOptionResult optionResult, string uid) = await userService.ProcessInputCookieAsync(cookie, isOversea).ConfigureAwait(false);
- switch (optionResult)
- {
- case UserOptionResult.Added:
- if (Users!.Count == 1)
- {
- await ThreadHelper.SwitchToMainThreadAsync();
- SelectedUser = Users.Single();
- }
-
- infoBarService.Success(string.Format(SH.ViewModelUserAdded, uid));
- break;
- case UserOptionResult.Incomplete:
- infoBarService.Information(SH.ViewModelUserIncomplete);
- break;
- case UserOptionResult.Invalid:
- infoBarService.Information(SH.ViewModelUserInvalid);
- break;
- case UserOptionResult.Updated:
- infoBarService.Success(string.Format(SH.ViewModelUserUpdated, uid));
- break;
- default:
- throw Must.NeverHappen();
- }
+ await HandleUserOptionResultAsync(optionResult, uid).ConfigureAwait(false);
}
}
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/ApiOsEndpoints.cs b/src/Snap.Hutao/Snap.Hutao/Web/ApiOsEndpoints.cs
index 88fd90c6..35cff726 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/ApiOsEndpoints.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/ApiOsEndpoints.cs
@@ -233,6 +233,14 @@ internal static class ApiOsEndpoints
}
#endregion
+ #region WebApiOsAccountApi
+
+ ///
+ /// 使用 Cookie 登录
+ ///
+ public const string WebApiOsAccountLoginByCookie = $"{WebApiOsAccountApi}/login_by_cookie";
+ #endregion
+
#region Hosts | Queries
private const string ApiNaGeetest = "https://api-na.geetest.com";
@@ -254,6 +262,9 @@ internal static class ApiOsEndpoints
private const string SgPublicApi = "https://sg-public-api.hoyolab.com";
+ private const string WebApiOs = "https://webapi-os.account.hoyoverse.com";
+ private const string WebApiOsAccountApi = $"{WebApiOs}/Api";
+
///
/// Web static referer
///