mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Upload spiral abyss record for hoyolab user & clean
This commit is contained in:
@@ -93,7 +93,7 @@ internal sealed class AvatarInfoDbOperation
|
||||
Response<RecordPlayerInfo> playerInfoResponse;
|
||||
Response<Web.Hoyolab.Takumi.GameRecord.Avatar.CharacterWrapper> charactersResponse;
|
||||
|
||||
if (userAndUid.Uid.Region == "cn_gf01" || userAndUid.Uid.Region == "cn_qd01")
|
||||
if (!userAndUid.User.IsOversea)
|
||||
{
|
||||
GameRecordClient gameRecordClient = Ioc.Default.GetRequiredService<GameRecordClient>();
|
||||
playerInfoResponse = await gameRecordClient
|
||||
|
||||
@@ -38,7 +38,7 @@ internal sealed class GachaLogQueryStokenProvider : IGachaLogQueryProvider
|
||||
{
|
||||
if (UserAndUid.TryFromUser(userService.Current, out UserAndUid? userAndUid))
|
||||
{
|
||||
if (userAndUid.Uid.Region != "cn_gf01" && userAndUid.Uid.Region != "cn_qd01")
|
||||
if (userAndUid.User.IsOversea)
|
||||
{
|
||||
return new(false, "Unsupported for hoyoverse account");
|
||||
}
|
||||
|
||||
@@ -75,15 +75,15 @@ internal class SpiralAbyssRecordService : ISpiralAbyssRecordService
|
||||
Response<Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss> response;
|
||||
|
||||
// server determination
|
||||
if (userAndUid.Uid.Region == "cn_gf01" || userAndUid.Uid.Region == "cn_qd01")
|
||||
if (userAndUid.User.IsOversea)
|
||||
{
|
||||
response = await gameRecordClient
|
||||
response = await gameRecordClientOs
|
||||
.GetSpiralAbyssAsync(userAndUid, schedule)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
response = await gameRecordClientOs
|
||||
response = await gameRecordClient
|
||||
.GetSpiralAbyssAsync(userAndUid, schedule)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -27,13 +27,15 @@
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox
|
||||
<TextBox
|
||||
TextChanging="TextBoxOnTextChanging"
|
||||
InputScope="Number"
|
||||
MaxLength="9"
|
||||
Grid.Column="0"
|
||||
Width="240"
|
||||
MaxLength="9"
|
||||
x:Name="UidInput"
|
||||
Margin="0,0,16,0"
|
||||
PlaceholderText="<EFBFBD><EFBFBD><EFBFBD><EFBFBD>дͨ<EFBFBD><EFBFBD>֤ID"
|
||||
PlaceholderText="Please fill in your User ID here"
|
||||
HorizontalAlignment="Right"/>
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
|
||||
@@ -2,27 +2,25 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.Service.User;
|
||||
using Snap.Hutao.View.Dialog;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
using Snap.Hutao.Web.Hoyolab.Passport;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Auth;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using System.Diagnostics.Eventing.Reader;
|
||||
|
||||
namespace Snap.Hutao.View.Page;
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>֤ҳ<EFBFBD><EFBFBD>
|
||||
/// 登录米哈游通行证页面
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Controls.Page
|
||||
{
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>µĵ<EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD>֤ҳ<EFBFBD><EFBFBD>
|
||||
/// 构造一个新的登录米哈游通行证页面
|
||||
/// </summary>
|
||||
public LoginHoyoverseUserPage()
|
||||
{
|
||||
@@ -65,14 +63,14 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
|
||||
if (uid.Length != 9)
|
||||
{
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
infoBarService.Warning($"<22><><EFBFBD><EFBFBD>ҳ<EFBFBD><D2B3><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>֤ ID!");
|
||||
infoBarService.Information($"请在页面右上方的输入框处填写你的通行证 ID!");
|
||||
return;
|
||||
}
|
||||
|
||||
Cookie loginTicketCookie = Cookie.FromCoreWebView2Cookies(cookies);
|
||||
loginTicketCookie["login_uid"] = uid;
|
||||
|
||||
// ʹ<EFBFBD><EFBFBD> loginTicket <EFBFBD><EFBFBD>ȡ stoken
|
||||
// 使用 loginTicket 获取 stoken
|
||||
Response<ListWrapper<NameToken>> multiTokenResponse = await Ioc.Default
|
||||
.GetRequiredService<AuthClientOs>()
|
||||
.GetMultiTokenByLoginTicketAsync(loginTicketCookie, token)
|
||||
@@ -86,7 +84,7 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
|
||||
Dictionary<string, string> multiTokenMap = multiTokenResponse.Data.List.ToDictionary(n => n.Name, n => n.Token);
|
||||
Cookie hoyoLabCookie = Cookie.Parse($"stoken={multiTokenMap["stoken"]}; stuid={uid}");
|
||||
|
||||
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> cookie <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>
|
||||
// 处理 cookie 并添加用户
|
||||
(UserOptionResult result, string nickname) = await Ioc.Default
|
||||
.GetRequiredService<IUserService>()
|
||||
.ProcessInputOsCookieAsync(hoyoLabCookie)
|
||||
@@ -104,16 +102,16 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
|
||||
vm.SelectedUser = vm.Users.Single();
|
||||
}
|
||||
|
||||
infoBarService.Success($"<EFBFBD>û<EFBFBD> [{nickname}] <EFBFBD><EFBFBD><EFBFBD>ӳɹ<EFBFBD>");
|
||||
infoBarService.Success($"用户 [{nickname}] 添加成功");
|
||||
break;
|
||||
case UserOptionResult.Incomplete:
|
||||
infoBarService.Information($"<EFBFBD><EFBFBD> Cookie <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>");
|
||||
infoBarService.Information($"此 Cookie 不完整,操作失败");
|
||||
break;
|
||||
case UserOptionResult.Invalid:
|
||||
infoBarService.Information($"<EFBFBD><EFBFBD> Cookie <EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>");
|
||||
infoBarService.Information($"此 Cookie 无效,操作失败");
|
||||
break;
|
||||
case UserOptionResult.Updated:
|
||||
infoBarService.Success($"<EFBFBD>û<EFBFBD> [{nickname}] <EFBFBD><EFBFBD><EFBFBD>³ɹ<EFBFBD>");
|
||||
infoBarService.Success($"用户 [{nickname}] 更新成功");
|
||||
break;
|
||||
default:
|
||||
throw Must.NeverHappen();
|
||||
@@ -124,4 +122,9 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
|
||||
{
|
||||
HandleCurrentCookieAsync(CancellationToken.None).SafeForget();
|
||||
}
|
||||
|
||||
private void TextBoxOnTextChanging(TextBox sender, TextBoxTextChangingEventArgs args)
|
||||
{
|
||||
sender.Text = new(sender.Text.Where(char.IsDigit).ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,8 +118,9 @@ internal sealed partial class Cookie
|
||||
|
||||
/// <summary>
|
||||
/// 提取其中的 stoken 信息
|
||||
/// Used for hoyolab account.
|
||||
/// </summary>
|
||||
/// <param name="cookie">含有 Stoken 的 cookie</param>
|
||||
/// <param name="cookie">A cookie contains stoken and stuid, without mid.</param>
|
||||
/// <returns>是否获取成功</returns>
|
||||
public bool TryGetAsStokenV1([NotNullWhen(true)] out Cookie? cookie)
|
||||
{
|
||||
|
||||
@@ -44,14 +44,16 @@ internal sealed class PassportClientOs
|
||||
public async Task<Response<UidCookieToken>> GetCookieAccountInfoBySTokenAsync(User user, CancellationToken token = default)
|
||||
{
|
||||
Response<UidCookieToken>? resp = null;
|
||||
string? stoken = user.SToken["stoken"];
|
||||
|
||||
if (stoken == null || user.Aid == null)
|
||||
if (user.SToken == null)
|
||||
{
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
StokenData data = new(stoken, user.Aid);
|
||||
string stoken = user.SToken.GetValueOrDefault(Cookie.STOKEN)!;
|
||||
|
||||
// Post json with stoken and uid (stuid/ltuid)
|
||||
StokenData data = new(stoken, user.Aid!);
|
||||
resp = await httpClient
|
||||
.SetUser(user, CookieType.SToken)
|
||||
.TryCatchPostAsJsonAsync<StokenData, Response<UidCookieToken>>(ApiOsEndpoints.AccountGetCookieTokenBySToken, data, options, logger, token)
|
||||
@@ -70,14 +72,16 @@ internal sealed class PassportClientOs
|
||||
public async Task<Response<LtokenWrapper>> GetLtokenBySTokenAsync(User user, CancellationToken token)
|
||||
{
|
||||
Response<LtokenWrapper>? resp = null;
|
||||
string? stoken = user.SToken["stoken"];
|
||||
|
||||
if (stoken == null || user.Aid == null)
|
||||
if (user.SToken == null)
|
||||
{
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
StokenData data = new(stoken, user.Aid);
|
||||
string stoken = user.SToken.GetValueOrDefault(Cookie.STOKEN)!;
|
||||
|
||||
// Post json with stoken and uid (stuid/ltuid)
|
||||
StokenData data = new(stoken, user.Aid!);
|
||||
resp = await httpClient
|
||||
.SetUser(user, CookieType.SToken)
|
||||
.TryCatchPostAsJsonAsync<StokenData, Response<LtokenWrapper>>(ApiOsEndpoints.AccountGetLtokenByStoken, data, options, logger, token)
|
||||
|
||||
@@ -80,18 +80,20 @@ internal sealed class CalculateClient
|
||||
Response<ListWrapper<Avatar>>? resp;
|
||||
|
||||
// 根据 uid 所属服务器选择 referer 与 api
|
||||
string referer = ApiOsEndpoints.ActHoyolabReferer;
|
||||
string endpoint = ApiOsEndpoints.CalculateOsSyncAvatarList;
|
||||
string referer;
|
||||
string endpoint;
|
||||
|
||||
if (userAndUid.Uid.Region == "cn_gf01" || userAndUid.Uid.Region == "cn_qd01")
|
||||
if (userAndUid.User.IsOversea)
|
||||
{
|
||||
referer = ApiEndpoints.WebStaticMihoyoReferer;
|
||||
endpoint = ApiEndpoints.CalculateSyncAvatarList;
|
||||
referer = ApiOsEndpoints.ActHoyolabReferer;
|
||||
endpoint = ApiOsEndpoints.CalculateOsSyncAvatarList;
|
||||
httpClient.SetUser(userAndUid.User, CookieType.CookieToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
httpClient.SetUser(userAndUid.User, CookieType.Cookie);
|
||||
referer = ApiEndpoints.WebStaticMihoyoReferer;
|
||||
endpoint = ApiEndpoints.CalculateSyncAvatarList;
|
||||
httpClient.SetUser(userAndUid.User, CookieType.CookieToken);
|
||||
}
|
||||
|
||||
do
|
||||
@@ -129,7 +131,7 @@ internal sealed class CalculateClient
|
||||
public async Task<Response<AvatarDetail>> GetAvatarDetailAsync(UserAndUid userAndUid, Avatar avatar, CancellationToken token = default)
|
||||
{
|
||||
Response<AvatarDetail>? resp;
|
||||
if (userAndUid.Uid.Region == "cn_gf01" || userAndUid.Uid.Region == "cn_qd01")
|
||||
if (!userAndUid.User.IsOversea)
|
||||
{
|
||||
resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.CookieToken)
|
||||
@@ -139,10 +141,11 @@ internal sealed class CalculateClient
|
||||
else
|
||||
{
|
||||
resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.Cookie)
|
||||
.SetUser(userAndUid.User, CookieType.CookieToken)
|
||||
.TryCatchGetFromJsonAsync<Response<AvatarDetail>>(ApiOsEndpoints.CalculateOsSyncAvatarDetail(avatar.Id, userAndUid.Uid.Value), options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ internal sealed class HomaSpiralAbyssClient
|
||||
{
|
||||
private readonly HttpClient httpClient;
|
||||
private readonly GameRecordClient gameRecordClient;
|
||||
private readonly GameRecordClientOs gameRecordClientOs;
|
||||
private readonly JsonSerializerOptions options;
|
||||
private readonly ILogger<HomaSpiralAbyssClient> logger;
|
||||
|
||||
@@ -33,10 +34,11 @@ internal sealed class HomaSpiralAbyssClient
|
||||
/// <param name="gameRecordClient">游戏记录客户端</param>
|
||||
/// <param name="options">json序列化选项</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
public HomaSpiralAbyssClient(HttpClient httpClient, GameRecordClient gameRecordClient, JsonSerializerOptions options, ILogger<HomaSpiralAbyssClient> logger)
|
||||
public HomaSpiralAbyssClient(HttpClient httpClient, GameRecordClient gameRecordClient, GameRecordClientOs gameRecordClientOs, JsonSerializerOptions options, ILogger<HomaSpiralAbyssClient> logger)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.gameRecordClient = gameRecordClient;
|
||||
this.gameRecordClientOs = gameRecordClientOs;
|
||||
this.options = options;
|
||||
this.logger = logger;
|
||||
}
|
||||
@@ -186,25 +188,55 @@ internal sealed class HomaSpiralAbyssClient
|
||||
/// <returns>玩家记录</returns>
|
||||
public async Task<SimpleRecord?> GetPlayerRecordAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
Response<PlayerInfo> playerInfoResponse = await gameRecordClient
|
||||
if (userAndUid.User.IsOversea)
|
||||
{
|
||||
// for oversea server
|
||||
Response<PlayerInfo> playerInfoResponse = await gameRecordClientOs
|
||||
.GetPlayerInfoAsync(userAndUid, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (playerInfoResponse.IsOk())
|
||||
{
|
||||
Response<CharacterWrapper> charactersResponse = await gameRecordClient
|
||||
.GetCharactersAsync(userAndUid, playerInfoResponse.Data, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (charactersResponse.IsOk())
|
||||
if (playerInfoResponse.IsOk())
|
||||
{
|
||||
Response<SpiralAbyss> spiralAbyssResponse = await gameRecordClient
|
||||
.GetSpiralAbyssAsync(userAndUid, SpiralAbyssSchedule.Current, token)
|
||||
.ConfigureAwait(false);
|
||||
Response<CharacterWrapper> charactersResponse = await gameRecordClientOs
|
||||
.GetCharactersAsync(userAndUid, playerInfoResponse.Data, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (spiralAbyssResponse.IsOk())
|
||||
if (charactersResponse.IsOk())
|
||||
{
|
||||
return new(userAndUid.Uid.Value, charactersResponse.Data.Avatars, spiralAbyssResponse.Data);
|
||||
Response<SpiralAbyss> spiralAbyssResponse = await gameRecordClientOs
|
||||
.GetSpiralAbyssAsync(userAndUid, SpiralAbyssSchedule.Current, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (spiralAbyssResponse.IsOk())
|
||||
{
|
||||
return new(userAndUid.Uid.Value, charactersResponse.Data.Avatars, spiralAbyssResponse.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// for cn server
|
||||
Response<PlayerInfo> playerInfoResponse = await gameRecordClient
|
||||
.GetPlayerInfoAsync(userAndUid, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (playerInfoResponse.IsOk())
|
||||
{
|
||||
Response<CharacterWrapper> charactersResponse = await gameRecordClient
|
||||
.GetCharactersAsync(userAndUid, playerInfoResponse.Data, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (charactersResponse.IsOk())
|
||||
{
|
||||
Response<SpiralAbyss> spiralAbyssResponse = await gameRecordClient
|
||||
.GetSpiralAbyssAsync(userAndUid, SpiralAbyssSchedule.Current, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (spiralAbyssResponse.IsOk())
|
||||
{
|
||||
return new(userAndUid.Uid.Value, charactersResponse.Data.Avatars, spiralAbyssResponse.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user