This commit is contained in:
DismissedLight
2023-03-27 18:39:02 +08:00
parent 97cbe7cf55
commit f90b828bb4
16 changed files with 109 additions and 185 deletions

View File

@@ -4723,7 +4723,7 @@ namespace Snap.Hutao.Resource.Localization {
} }
/// <summary> /// <summary>
/// 查找类似 Cookie 操作 的本地化字符串。 /// 查找类似 米游社 的本地化字符串。
/// </summary> /// </summary>
internal static string ViewUserCookieOperation { internal static string ViewUserCookieOperation {
get { get {

View File

@@ -1639,7 +1639,7 @@
<value>工具</value> <value>工具</value>
</data> </data>
<data name="ViewUserCookieOperation" xml:space="preserve"> <data name="ViewUserCookieOperation" xml:space="preserve">
<value>Cookie 操作</value> <value>米游社</value>
</data> </data>
<data name="ViewUserCookieOperationLoginMihoyoUserAction" xml:space="preserve"> <data name="ViewUserCookieOperationLoginMihoyoUserAction" xml:space="preserve">
<value>网页登录</value> <value>网页登录</value>

View File

@@ -109,9 +109,8 @@ internal sealed class DailyNoteService : IDailyNoteService, IRecipient<UserRemov
using (IServiceScope scope = scopeFactory.CreateScope()) using (IServiceScope scope = scopeFactory.CreateScope())
{ {
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>(); AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
GameRecordClient gameRecordClient = scope.ServiceProvider.GetRequiredService<GameRecordClient>();
GameRecordClientOversea gameRecordClientOs = scope.ServiceProvider.GetRequiredService<GameRecordClientOversea>();
// TODO: Add this option to AppOptions
bool isSilentMode = appDbContext.Settings bool isSilentMode = appDbContext.Settings
.SingleOrAdd(SettingEntry.DailyNoteSilentWhenPlayingGame, Core.StringLiterals.False) .SingleOrAdd(SettingEntry.DailyNoteSilentWhenPlayingGame, Core.StringLiterals.False)
.GetBoolean(); .GetBoolean();

View File

@@ -35,7 +35,7 @@
HorizontalAlignment="Right" HorizontalAlignment="Right"
InputScope="Number" InputScope="Number"
MaxLength="9" MaxLength="9"
PlaceholderText="Please fill in your User ID here"/> PlaceholderText="{shcm:ResourceString Name=ViewPageLoginHoyoverseUserHint}"/>
<Button <Button
Grid.Column="1" Grid.Column="1"
Click="CookieButtonClick" Click="CookieButtonClick"

View File

@@ -61,7 +61,7 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
if (uid.Length != 9) if (uid.Length != 9)
{ {
await ThreadHelper.SwitchToMainThreadAsync(); await ThreadHelper.SwitchToMainThreadAsync();
infoBarService.Information($"请在页面右上方的输入框处填写你的通行证 ID!"); infoBarService.Information(SH.ViewPageLoginHoyoverseUserHint);
return; return;
} }
@@ -80,7 +80,7 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
} }
Dictionary<string, string> multiTokenMap = multiTokenResponse.Data.List.ToDictionary(n => n.Name, n => n.Token); Dictionary<string, string> multiTokenMap = multiTokenResponse.Data.List.ToDictionary(n => n.Name, n => n.Token);
Cookie hoyoLabCookie = Cookie.Parse($"stoken={multiTokenMap["stoken"]}; stuid={uid}"); Cookie hoyoLabCookie = Cookie.Parse($"{Cookie.STUID}={uid};{Cookie.STOKEN}={multiTokenMap[Cookie.STOKEN]}");
// 处理 cookie 并添加用户 // 处理 cookie 并添加用户
(UserOptionResult result, string nickname) = await Ioc.Default (UserOptionResult result, string nickname) = await Ioc.Default
@@ -100,16 +100,16 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
vm.SelectedUser = vm.Users.Single(); vm.SelectedUser = vm.Users.Single();
} }
infoBarService.Success($"用户 [{nickname}] 添加成功"); infoBarService.Success(string.Format(SH.ViewModelUserAdded, nickname));
break; break;
case UserOptionResult.Incomplete: case UserOptionResult.Incomplete:
infoBarService.Information($"此 Cookie 不完整,操作失败"); infoBarService.Information(SH.ViewModelUserIncomplete);
break; break;
case UserOptionResult.Invalid: case UserOptionResult.Invalid:
infoBarService.Information($"此 Cookie 无效,操作失败"); infoBarService.Information(SH.ViewModelUserInvalid);
break; break;
case UserOptionResult.Updated: case UserOptionResult.Updated:
infoBarService.Success($"用户 [{nickname}] 更新成功"); infoBarService.Success(string.Format(SH.ViewModelUserUpdated, nickname));
break; break;
default: default:
throw Must.NeverHappen(); throw Must.NeverHappen();

View File

@@ -67,9 +67,10 @@ internal sealed partial class LoginMihoyoUserPage : Microsoft.UI.Xaml.Controls.P
Dictionary<string, string> multiTokenMap = multiTokenResponse.Data.List.ToDictionary(n => n.Name, n => n.Token); Dictionary<string, string> multiTokenMap = multiTokenResponse.Data.List.ToDictionary(n => n.Name, n => n.Token);
Cookie stokenV1 = Cookie.Parse($"stuid={loginTicketCookie["login_uid"]};stoken={multiTokenMap["stoken"]}"); Cookie stokenV1 = Cookie.Parse($"{Cookie.STUID}={loginTicketCookie[Cookie.LOGIN_UID]};{Cookie.STOKEN}={multiTokenMap[Cookie.STOKEN]}");
Response<LoginResult> loginResultResponse = await Ioc.Default Response<LoginResult> loginResultResponse = await Ioc.Default
.GetRequiredService<PassportClient2>() .GetRequiredService<PassportClient>()
.LoginBySTokenAsync(stokenV1, token) .LoginBySTokenAsync(stokenV1, token)
.ConfigureAwait(false); .ConfigureAwait(false);
@@ -87,6 +88,7 @@ internal sealed partial class LoginMihoyoUserPage : Microsoft.UI.Xaml.Controls.P
Ioc.Default.GetRequiredService<INavigationService>().GoBack(); Ioc.Default.GetRequiredService<INavigationService>().GoBack();
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>(); IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
// TODO: Move these code somewhere else.
switch (result) switch (result)
{ {
case UserOptionResult.Added: case UserOptionResult.Added:
@@ -97,16 +99,16 @@ internal sealed partial class LoginMihoyoUserPage : Microsoft.UI.Xaml.Controls.P
vm.SelectedUser = vm.Users.Single(); vm.SelectedUser = vm.Users.Single();
} }
infoBarService.Success($"用户 [{nickname}] 添加成功"); infoBarService.Success(string.Format(SH.ViewModelUserAdded, nickname));
break; break;
case UserOptionResult.Incomplete: case UserOptionResult.Incomplete:
infoBarService.Information($"此 Cookie 不完整,操作失败"); infoBarService.Information(SH.ViewModelUserIncomplete);
break; break;
case UserOptionResult.Invalid: case UserOptionResult.Invalid:
infoBarService.Information($"此 Cookie 无效,操作失败"); infoBarService.Information(SH.ViewModelUserInvalid);
break; break;
case UserOptionResult.Updated: case UserOptionResult.Updated:
infoBarService.Success($"用户 [{nickname}] 更新成功"); infoBarService.Success(string.Format(SH.ViewModelUserUpdated, nickname));
break; break;
default: default:
throw Must.NeverHappen(); throw Must.NeverHappen();

View File

@@ -238,7 +238,7 @@
Icon="{shcm:FontIcon Glyph=&#xEB41;}" Icon="{shcm:FontIcon Glyph=&#xEB41;}"
Label="{shcm:ResourceString Name=ViewUserCookieOperationLoginMihoyoUserAction}"/> Label="{shcm:ResourceString Name=ViewUserCookieOperationLoginMihoyoUserAction}"/>
<AppBarButton <AppBarButton
Command="{Binding AddOsUserCommand}" Command="{Binding AddOverseaUserCommand}"
Icon="{shcm:FontIcon Glyph=&#xE710;}" Icon="{shcm:FontIcon Glyph=&#xE710;}"
Label="{shcm:ResourceString Name=ViewUserCookieOperationManualInputAction}"/> Label="{shcm:ResourceString Name=ViewUserCookieOperationManualInputAction}"/>
</StackPanel> </StackPanel>

View File

@@ -46,7 +46,7 @@ internal sealed class UserViewModel : ObservableObject
OpenUICommand = new AsyncRelayCommand(OpenUIAsync); OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
AddUserCommand = new AsyncRelayCommand(AddUserAsync); AddUserCommand = new AsyncRelayCommand(AddUserAsync);
AddOsUserCommand = new AsyncRelayCommand(AddOsUserAsync); AddOverseaUserCommand = new AsyncRelayCommand(AddOverseaUserAsync);
LoginMihoyoUserCommand = new RelayCommand(LoginMihoyoUser); LoginMihoyoUserCommand = new RelayCommand(LoginMihoyoUser);
LoginHoyoverseUserCommand = new RelayCommand(LoginHoyoverseUser); LoginHoyoverseUserCommand = new RelayCommand(LoginHoyoverseUser);
RemoveUserCommand = new AsyncRelayCommand<User>(RemoveUserAsync); RemoveUserCommand = new AsyncRelayCommand<User>(RemoveUserAsync);
@@ -92,7 +92,7 @@ internal sealed class UserViewModel : ObservableObject
/// <summary> /// <summary>
/// 添加国际服用户命令 /// 添加国际服用户命令
/// </summary> /// </summary>
public ICommand AddOsUserCommand { get; } public ICommand AddOverseaUserCommand { get; }
/// <summary> /// <summary>
/// 登录米游社命令 /// 登录米游社命令
@@ -132,48 +132,17 @@ internal sealed class UserViewModel : ObservableObject
} }
} }
private async Task AddUserAsync() private Task AddUserAsync()
{ {
// ContentDialog must be created by main thread. return AddUserCoreAsync(false);
await ThreadHelper.SwitchToMainThreadAsync();
// Get cookie from user input
ValueResult<bool, string> result = await new UserDialog().GetInputCookieAsync().ConfigureAwait(false);
// User confirms the input
if (result.IsOk)
{
Cookie cookie = Cookie.Parse(result.Value);
(UserOptionResult optionResult, string uid) = await userService.ProcessInputCookieAsync(cookie).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();
}
}
} }
private async Task AddOsUserAsync() private Task AddOverseaUserAsync()
{
return AddUserCoreAsync(true);
}
private async Task AddUserCoreAsync(bool isOversea)
{ {
// ContentDialog must be created by main thread. // ContentDialog must be created by main thread.
await ThreadHelper.SwitchToMainThreadAsync(); await ThreadHelper.SwitchToMainThreadAsync();
@@ -186,7 +155,7 @@ internal sealed class UserViewModel : ObservableObject
{ {
Cookie cookie = Cookie.Parse(result.Value); Cookie cookie = Cookie.Parse(result.Value);
(UserOptionResult optionResult, string uid) = await userService.ProcessInputOsCookieAsync(cookie).ConfigureAwait(false); (UserOptionResult optionResult, string uid) = await userService.ProcessInputCookieAsync(cookie, isOversea).ConfigureAwait(false);
switch (optionResult) switch (optionResult)
{ {

View File

@@ -200,7 +200,7 @@ internal static class ApiOsEndpoints
/// <summary> /// <summary>
/// 计算器结果 /// 计算器结果
/// </summary> /// </summary>
public const string CalculateOsCompute = $"{SgPublicApi}/event/calculateos/compute"; public const string CalculateCompute = $"{SgPublicApi}/event/calculateos/compute";
/// <summary> /// <summary>
/// 计算器同步角色详情 size 20 /// 计算器同步角色详情 size 20
@@ -208,7 +208,7 @@ internal static class ApiOsEndpoints
/// <param name="avatarId">角色Id</param> /// <param name="avatarId">角色Id</param>
/// <param name="uid">uid</param> /// <param name="uid">uid</param>
/// <returns>角色详情</returns> /// <returns>角色详情</returns>
public static string CalculateOsSyncAvatarDetail(AvatarId avatarId, PlayerUid uid) public static string CalculateSyncAvatarDetail(AvatarId avatarId, PlayerUid uid)
{ {
return $"{SgPublicApi}/event/calculateos/sync/avatar/detail?avatar_id={avatarId.Value}&uid={uid.Value}&region={uid.Region}"; return $"{SgPublicApi}/event/calculateos/sync/avatar/detail?avatar_id={avatarId.Value}&uid={uid.Value}&region={uid.Region}";
} }
@@ -216,7 +216,7 @@ internal static class ApiOsEndpoints
/// <summary> /// <summary>
/// 计算器同步角色列表 size 20 /// 计算器同步角色列表 size 20
/// </summary> /// </summary>
public const string CalculateOsSyncAvatarList = $"{SgPublicApi}/event/calculateos/sync/avatar/list"; public const string CalculateSyncAvatarList = $"{SgPublicApi}/event/calculateos/sync/avatar/list";
#endregion #endregion

View File

@@ -4,8 +4,10 @@
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient; using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity;
using Snap.Hutao.Web.Hoyolab.Annotation; using Snap.Hutao.Web.Hoyolab.Annotation;
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
using Snap.Hutao.Web.Response; using Snap.Hutao.Web.Response;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Json;
namespace Snap.Hutao.Web.Hoyolab.Passport; namespace Snap.Hutao.Web.Hoyolab.Passport;
@@ -13,6 +15,7 @@ namespace Snap.Hutao.Web.Hoyolab.Passport;
/// 通行证客户端 /// 通行证客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret]
[HttpClient(HttpClientConfiguration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class PassportClient internal sealed class PassportClient
{ {
@@ -34,7 +37,7 @@ internal sealed class PassportClient
} }
/// <summary> /// <summary>
/// 异步验证Ltoken /// 异步验证 LToken
/// </summary> /// </summary>
/// <param name="user">用户</param> /// <param name="user">用户</param>
/// <param name="token">取消令牌</param> /// <param name="token">取消令牌</param>
@@ -50,6 +53,28 @@ internal sealed class PassportClient
return Response.Response.DefaultIfNull(response); return Response.Response.DefaultIfNull(response);
} }
/// <summary>
/// V1 SToken 登录
/// </summary>
/// <param name="stokenV1">v1 SToken</param>
/// <param name="token">取消令牌</param>
/// <returns>登录数据</returns>
[ApiInformation(Salt = SaltType.PROD)]
public async Task<Response<LoginResult>> LoginBySTokenAsync(Cookie stokenV1, CancellationToken token)
{
HttpResponseMessage message = await httpClient
.SetHeader("Cookie", stokenV1.ToString())
.UseDynamicSecret(DynamicSecretVersion.Gen2, SaltType.PROD, true)
.PostAsync(ApiEndpoints.AccountGetSTokenByOldToken, null, token)
.ConfigureAwait(false);
Response<LoginResult>? resp = await message.Content
.ReadFromJsonAsync<Response<LoginResult>>(options, token)
.ConfigureAwait(false);
return Response.Response.DefaultIfNull(resp);
}
private class Timestamp private class Timestamp
{ {
[JsonPropertyName("t")] [JsonPropertyName("t")]

View File

@@ -39,28 +39,6 @@ internal sealed class PassportClient2 : IPassportClient
/// <inheritdoc/> /// <inheritdoc/>
public bool IsOversea => false; public bool IsOversea => false;
/// <summary>
/// V1 SToken 登录
/// </summary>
/// <param name="stokenV1">v1 SToken</param>
/// <param name="token">取消令牌</param>
/// <returns>登录数据</returns>
[ApiInformation(Salt = SaltType.PROD)]
public async Task<Response<LoginResult>> LoginBySTokenAsync(Cookie stokenV1, CancellationToken token)
{
HttpResponseMessage message = await httpClient
.SetHeader("Cookie", stokenV1.ToString())
.UseDynamicSecret(DynamicSecretVersion.Gen2, SaltType.PROD, true)
.PostAsync(ApiEndpoints.AccountGetSTokenByOldToken, null, token)
.ConfigureAwait(false);
Response<LoginResult>? resp = await message.Content
.ReadFromJsonAsync<Response<LoginResult>>(options, token)
.ConfigureAwait(false);
return Response.Response.DefaultIfNull(resp);
}
/// <summary> /// <summary>
/// 异步获取 CookieToken /// 异步获取 CookieToken
/// </summary> /// </summary>

View File

@@ -20,7 +20,7 @@ internal sealed class PassportClientOversea : IPassportClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;
private readonly JsonSerializerOptions options; private readonly JsonSerializerOptions options;
private readonly ILogger<PassportClient> logger; private readonly ILogger<PassportClientOversea> logger;
/// <summary> /// <summary>
/// 构造一个新的国际服通行证客户端 /// 构造一个新的国际服通行证客户端
@@ -28,7 +28,7 @@ internal sealed class PassportClientOversea : IPassportClient
/// <param name="httpClient">http客户端</param> /// <param name="httpClient">http客户端</param>
/// <param name="options">Json序列化选项</param> /// <param name="options">Json序列化选项</param>
/// <param name="logger">日志器</param> /// <param name="logger">日志器</param>
public PassportClientOversea(HttpClient httpClient, JsonSerializerOptions options, ILogger<PassportClient> logger) public PassportClientOversea(HttpClient httpClient, JsonSerializerOptions options, ILogger<PassportClientOversea> logger)
{ {
this.httpClient = httpClient; this.httpClient = httpClient;
this.options = options; this.options = options;

View File

@@ -40,7 +40,7 @@ internal sealed class ResourceClient
/// <returns>游戏资源</returns> /// <returns>游戏资源</returns>
public async Task<Response<GameResource>> GetResourceAsync(LaunchScheme scheme, CancellationToken token = default) public async Task<Response<GameResource>> GetResourceAsync(LaunchScheme scheme, CancellationToken token = default)
{ {
string url = scheme.LauncherId == "10" string url = scheme.IsOversea
? ApiOsEndpoints.SdkOsStaticLauncherResource(scheme) ? ApiOsEndpoints.SdkOsStaticLauncherResource(scheme)
: ApiEndpoints.SdkStaticLauncherResource(scheme); : ApiEndpoints.SdkStaticLauncherResource(scheme);

View File

@@ -55,7 +55,7 @@ internal sealed class BindingClient2
/// <summary> /// <summary>
/// 异步生成祈愿验证密钥 /// 异步生成祈愿验证密钥
/// 需要stoken /// 需要 SToken
/// </summary> /// </summary>
/// <param name="user">用户</param> /// <param name="user">用户</param>
/// <param name="data">提交数据</param> /// <param name="data">提交数据</param>

View File

@@ -43,24 +43,19 @@ internal sealed class CalculateClient
[ApiInformation(Cookie = CookieType.Cookie)] [ApiInformation(Cookie = CookieType.Cookie)]
public async Task<Response<Consumption>> ComputeAsync(Model.Entity.User user, AvatarPromotionDelta delta, CancellationToken token = default) public async Task<Response<Consumption>> ComputeAsync(Model.Entity.User user, AvatarPromotionDelta delta, CancellationToken token = default)
{ {
Response<Consumption>? resp; string referer = user.IsOversea
? ApiOsEndpoints.ActHoyolabReferer
: ApiEndpoints.WebStaticMihoyoReferer;
if (user.IsOversea) string url = user.IsOversea
{ ? ApiOsEndpoints.CalculateCompute
resp = await httpClient : ApiEndpoints.CalculateCompute;
Response<Consumption>? resp = await httpClient
.SetUser(user, CookieType.Cookie) .SetUser(user, CookieType.Cookie)
.SetReferer(ApiOsEndpoints.ActHoyolabReferer) .SetReferer(referer)
.TryCatchPostAsJsonAsync<AvatarPromotionDelta, Response<Consumption>>(ApiOsEndpoints.CalculateOsCompute, delta, options, logger, token) .TryCatchPostAsJsonAsync<AvatarPromotionDelta, Response<Consumption>>(url, delta, options, logger, token)
.ConfigureAwait(false); .ConfigureAwait(false);
}
else
{
resp = await httpClient
.SetUser(user, CookieType.Cookie)
.SetReferer(ApiEndpoints.WebStaticMihoyoReferer)
.TryCatchPostAsJsonAsync<AvatarPromotionDelta, Response<Consumption>>(ApiEndpoints.CalculateCompute, delta, options, logger, token)
.ConfigureAwait(false);
}
return Response.Response.DefaultIfNull(resp); return Response.Response.DefaultIfNull(resp);
} }
@@ -80,28 +75,22 @@ internal sealed class CalculateClient
Response<ListWrapper<Avatar>>? resp; Response<ListWrapper<Avatar>>? resp;
// 根据 uid 所属服务器选择 referer 与 api // 根据 uid 所属服务器选择 referer 与 api
string referer; string referer = userAndUid.User.IsOversea
string endpoint; ? ApiOsEndpoints.ActHoyolabReferer
: ApiEndpoints.WebStaticMihoyoReferer;
string url = userAndUid.User.IsOversea
? ApiOsEndpoints.CalculateSyncAvatarList
: ApiEndpoints.CalculateSyncAvatarList;
if (userAndUid.User.IsOversea) httpClient
{ .SetReferer(referer)
referer = ApiOsEndpoints.ActHoyolabReferer; .SetUser(userAndUid.User, CookieType.CookieToken);
endpoint = ApiOsEndpoints.CalculateOsSyncAvatarList;
httpClient.SetUser(userAndUid.User, CookieType.CookieToken);
}
else
{
referer = ApiEndpoints.WebStaticMihoyoReferer;
endpoint = ApiEndpoints.CalculateSyncAvatarList;
httpClient.SetUser(userAndUid.User, CookieType.CookieToken);
}
do do
{ {
filter.Page = currentPage++; filter.Page = currentPage++;
resp = await httpClient resp = await httpClient
.SetReferer(referer) .TryCatchPostAsJsonAsync<SyncAvatarFilter, Response<ListWrapper<Avatar>>>(url, filter, options, logger, token)
.TryCatchPostAsJsonAsync<SyncAvatarFilter, Response<ListWrapper<Avatar>>>(endpoint, filter, options, logger, token)
.ConfigureAwait(false); .ConfigureAwait(false);
if (resp != null && resp.IsOk()) if (resp != null && resp.IsOk())
@@ -130,21 +119,14 @@ internal sealed class CalculateClient
/// <returns>角色详情</returns> /// <returns>角色详情</returns>
public async Task<Response<AvatarDetail>> GetAvatarDetailAsync(UserAndUid userAndUid, Avatar avatar, CancellationToken token = default) public async Task<Response<AvatarDetail>> GetAvatarDetailAsync(UserAndUid userAndUid, Avatar avatar, CancellationToken token = default)
{ {
Response<AvatarDetail>? resp; string url = userAndUid.User.IsOversea
if (!userAndUid.User.IsOversea) ? ApiOsEndpoints.CalculateSyncAvatarDetail(avatar.Id, userAndUid.Uid.Value)
{ : ApiEndpoints.CalculateSyncAvatarDetail(avatar.Id, userAndUid.Uid.Value);
resp = await httpClient
Response<AvatarDetail>? resp = await httpClient
.SetUser(userAndUid.User, CookieType.CookieToken) .SetUser(userAndUid.User, CookieType.CookieToken)
.TryCatchGetFromJsonAsync<Response<AvatarDetail>>(ApiEndpoints.CalculateSyncAvatarDetail(avatar.Id, userAndUid.Uid.Value), options, logger, token) .TryCatchGetFromJsonAsync<Response<AvatarDetail>>(url, options, logger, token)
.ConfigureAwait(false); .ConfigureAwait(false);
}
else
{
resp = await httpClient
.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); return Response.Response.DefaultIfNull(resp);
} }

View File

@@ -21,9 +21,8 @@ namespace Snap.Hutao.Web.Hutao;
[HttpClient(HttpClientConfiguration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class HomaSpiralAbyssClient internal sealed class HomaSpiralAbyssClient
{ {
private readonly IServiceProvider serviceProvider;
private readonly HttpClient httpClient; private readonly HttpClient httpClient;
private readonly GameRecordClient gameRecordClient;
private readonly GameRecordClientOversea gameRecordClientOs;
private readonly JsonSerializerOptions options; private readonly JsonSerializerOptions options;
private readonly ILogger<HomaSpiralAbyssClient> logger; private readonly ILogger<HomaSpiralAbyssClient> logger;
@@ -31,16 +30,14 @@ internal sealed class HomaSpiralAbyssClient
/// 构造一个新的胡桃API客户端 /// 构造一个新的胡桃API客户端
/// </summary> /// </summary>
/// <param name="httpClient">http客户端</param> /// <param name="httpClient">http客户端</param>
/// <param name="gameRecordClient">游戏记录客户端</param> /// <param name="serviceProvider">服务提供器</param>
/// <param name="options">json序列化选项</param> public HomaSpiralAbyssClient(HttpClient httpClient, IServiceProvider serviceProvider)
/// <param name="logger">日志器</param>
public HomaSpiralAbyssClient(HttpClient httpClient, GameRecordClient gameRecordClient, GameRecordClientOversea gameRecordClientOs, JsonSerializerOptions options, ILogger<HomaSpiralAbyssClient> logger)
{ {
options = serviceProvider.GetRequiredService<JsonSerializerOptions>();
logger = serviceProvider.GetRequiredService<ILogger<HomaSpiralAbyssClient>>();
this.serviceProvider = serviceProvider;
this.httpClient = httpClient; this.httpClient = httpClient;
this.gameRecordClient = gameRecordClient;
this.gameRecordClientOs = gameRecordClientOs;
this.options = options;
this.logger = logger;
} }
/// <summary> /// <summary>
@@ -188,55 +185,27 @@ internal sealed class HomaSpiralAbyssClient
/// <returns>玩家记录</returns> /// <returns>玩家记录</returns>
public async Task<SimpleRecord?> GetPlayerRecordAsync(UserAndUid userAndUid, CancellationToken token = default) public async Task<SimpleRecord?> GetPlayerRecordAsync(UserAndUid userAndUid, CancellationToken token = default)
{ {
if (userAndUid.User.IsOversea) IGameRecordClient gameRecordClient = serviceProvider.PickRequiredService<IGameRecordClient>(userAndUid.User.IsOversea);
{
// for oversea server Response<PlayerInfo> playerInfoResponse = await gameRecordClient
Response<PlayerInfo> playerInfoResponse = await gameRecordClientOs
.GetPlayerInfoAsync(userAndUid, token) .GetPlayerInfoAsync(userAndUid, token)
.ConfigureAwait(false); .ConfigureAwait(false);
if (playerInfoResponse.IsOk()) if (playerInfoResponse.IsOk())
{
Response<CharacterWrapper> charactersResponse = await gameRecordClientOs
.GetCharactersAsync(userAndUid, playerInfoResponse.Data, token)
.ConfigureAwait(false);
if (charactersResponse.IsOk())
{
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<CharacterWrapper> charactersResponse = await gameRecordClient
Response<PlayerInfo> playerInfoResponse = await gameRecordClient .GetCharactersAsync(userAndUid, playerInfoResponse.Data, token)
.GetPlayerInfoAsync(userAndUid, token) .ConfigureAwait(false);
.ConfigureAwait(false);
if (playerInfoResponse.IsOk()) if (charactersResponse.IsOk())
{ {
Response<CharacterWrapper> charactersResponse = await gameRecordClient Response<SpiralAbyss> spiralAbyssResponse = await gameRecordClient
.GetCharactersAsync(userAndUid, playerInfoResponse.Data, token) .GetSpiralAbyssAsync(userAndUid, SpiralAbyssSchedule.Current, token)
.ConfigureAwait(false); .ConfigureAwait(false);
if (charactersResponse.IsOk()) if (spiralAbyssResponse.IsOk())
{ {
Response<SpiralAbyss> spiralAbyssResponse = await gameRecordClient return new(userAndUid.Uid.Value, charactersResponse.Data.Avatars, spiralAbyssResponse.Data);
.GetSpiralAbyssAsync(userAndUid, SpiralAbyssSchedule.Current, token)
.ConfigureAwait(false);
if (spiralAbyssResponse.IsOk())
{
return new(userAndUid.Uid.Value, charactersResponse.Data.Avatars, spiralAbyssResponse.Data);
}
} }
} }
} }