fixup some code style phase 1

This commit is contained in:
DismissedLight
2023-03-25 21:26:17 +08:00
parent 523374ed3d
commit 09abb46159
38 changed files with 213 additions and 189 deletions

View File

@@ -11,7 +11,7 @@ using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
namespace Snap.Hutao.SourceGeneration.DedendencyInjection; namespace Snap.Hutao.SourceGeneration.DependencyInjection;
/// <summary> /// <summary>
/// 注入HttpClient代码生成器 /// 注入HttpClient代码生成器
@@ -21,10 +21,10 @@ namespace Snap.Hutao.SourceGeneration.DedendencyInjection;
[Generator] [Generator]
public class HttpClientGenerator : ISourceGenerator public class HttpClientGenerator : ISourceGenerator
{ {
private const string DefaultName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfigration.Default"; private const string DefaultName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfiguration.Default";
private const string XRpcName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfigration.XRpc"; private const string XRpcName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfiguration.XRpc";
private const string XRpc2Name = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfigration.XRpc2"; private const string XRpc2Name = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfiguration.XRpc2";
private const string XRpc3Name = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfigration.XRpc3"; private const string XRpc3Name = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.HttpClientConfiguration.XRpc3";
private const string PrimaryHttpMessageHandlerAttributeName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.PrimaryHttpMessageHandlerAttribute"; private const string PrimaryHttpMessageHandlerAttributeName = "Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient.PrimaryHttpMessageHandlerAttribute";
private const string DynamicSecretAttributeName = "Snap.Hutao.Web.Hoyolab.DynamicSecret.UseDynamicSecretAttribute"; private const string DynamicSecretAttributeName = "Snap.Hutao.Web.Hoyolab.DynamicSecret.UseDynamicSecretAttribute";
@@ -49,29 +49,34 @@ public class HttpClientGenerator : ISourceGenerator
StringBuilder sourceCodeBuilder = new(); StringBuilder sourceCodeBuilder = new();
sourceCodeBuilder.Append($@"// Copyright (c) DGP Studio. All rights reserved. sourceCodeBuilder.Append($$"""
// Licensed under the MIT license. // Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
// This class is generated by Snap.Hutao.SourceGeneration // This class is generated by Snap.Hutao.SourceGeneration
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Snap.Hutao.Web.Hoyolab.DynamicSecret; using Snap.Hutao.Web.Hoyolab.DynamicSecret;
using System.Net.Http; using System.Net.Http;
namespace Snap.Hutao.Core.DependencyInjection; namespace Snap.Hutao.Core.DependencyInjection;
internal static partial class IocHttpClientConfiguration internal static partial class IocHttpClientConfiguration
{{ {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(""{toolName}"",""1.0.0.0"")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{toolName}}","1.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static partial IServiceCollection AddHttpClients(this IServiceCollection services) public static partial IServiceCollection AddHttpClients(this IServiceCollection services)
{{"); {
""");
FillWithInjectionServices(receiver, sourceCodeBuilder); FillWithInjectionServices(receiver, sourceCodeBuilder);
sourceCodeBuilder.Append(@"
return services; sourceCodeBuilder.Append("""
}
}"); return services;
}
}
""");
context.AddSource("IocHttpClientConfiguration.g.cs", SourceText.From(sourceCodeBuilder.ToString(), Encoding.UTF8)); context.AddSource("IocHttpClientConfiguration.g.cs", SourceText.From(sourceCodeBuilder.ToString(), Encoding.UTF8));
} }
@@ -110,7 +115,7 @@ internal static partial class IocHttpClientConfiguration
lineBuilder.Append("XRpc3Configuration)"); lineBuilder.Append("XRpc3Configuration)");
break; break;
default: default:
throw new InvalidOperationException($"非法的HttpClientConfigration值: [{injectAsName}]"); throw new InvalidOperationException($"非法的 HttpClientConfiguration 值: [{injectAsName}]");
} }
AttributeData? handlerInfo = classSymbol AttributeData? handlerInfo = classSymbol
@@ -124,11 +129,11 @@ internal static partial class IocHttpClientConfiguration
foreach (KeyValuePair<string, TypedConstant> property in properties) foreach (KeyValuePair<string, TypedConstant> property in properties)
{ {
lineBuilder.Append(" "); lineBuilder.Append(' ');
lineBuilder.Append(property.Key); lineBuilder.Append(property.Key);
lineBuilder.Append(" = "); lineBuilder.Append(" = ");
lineBuilder.Append(property.Value.ToCSharpString()); lineBuilder.Append(property.Value.ToCSharpString());
lineBuilder.Append(","); lineBuilder.Append(',');
} }
lineBuilder.Append(" })"); lineBuilder.Append(" })");
@@ -139,7 +144,7 @@ internal static partial class IocHttpClientConfiguration
lineBuilder.Append(".AddHttpMessageHandler<DynamicSecretHandler>()"); lineBuilder.Append(".AddHttpMessageHandler<DynamicSecretHandler>()");
} }
lineBuilder.Append(";"); lineBuilder.Append(';');
lines.Add(lineBuilder.ToString()); lines.Add(lineBuilder.ToString());
} }

View File

@@ -11,7 +11,7 @@ using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
namespace Snap.Hutao.SourceGeneration.DedendencyInjection; namespace Snap.Hutao.SourceGeneration.DependencyInjection;
/// <summary> /// <summary>
/// 注入代码生成器 /// 注入代码生成器
@@ -44,27 +44,30 @@ public class InjectionGenerator : ISourceGenerator
string toolName = this.GetGeneratorType().FullName; string toolName = this.GetGeneratorType().FullName;
StringBuilder sourceCodeBuilder = new(); StringBuilder sourceCodeBuilder = new();
sourceCodeBuilder.Append($@"// Copyright (c) DGP Studio. All rights reserved. sourceCodeBuilder.Append($$"""
// Licensed under the MIT license. // Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
// This class is generated by Snap.Hutao.SourceGeneration // This class is generated by Snap.Hutao.SourceGeneration
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace Snap.Hutao.Core.DependencyInjection; namespace Snap.Hutao.Core.DependencyInjection;
internal static partial class ServiceCollectionExtension internal static partial class ServiceCollectionExtension
{{ {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute(""{toolName}"",""1.0.0.0"")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{toolName}}","1.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static partial IServiceCollection AddInjections(this IServiceCollection services) public static partial IServiceCollection AddInjections(this IServiceCollection services)
{{"); {
""");
FillWithInjectionServices(receiver, sourceCodeBuilder); FillWithInjectionServices(receiver, sourceCodeBuilder);
sourceCodeBuilder.Append(@" sourceCodeBuilder.Append("""
return services; return services;
} }
}"); }
""");
context.AddSource("ServiceCollectionExtension.g.cs", SourceText.From(sourceCodeBuilder.ToString(), Encoding.UTF8)); context.AddSource("ServiceCollectionExtension.g.cs", SourceText.From(sourceCodeBuilder.ToString(), Encoding.UTF8));
} }

View File

@@ -18,7 +18,7 @@ namespace Snap.Hutao.Core.Caching;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[Injection(InjectAs.Singleton, typeof(IImageCache))] [Injection(InjectAs.Singleton, typeof(IImageCache))]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
[PrimaryHttpMessageHandler(MaxConnectionsPerServer = 8)] [PrimaryHttpMessageHandler(MaxConnectionsPerServer = 8)]
internal sealed class ImageCache : IImageCache, IImageCacheFilePathOperation internal sealed class ImageCache : IImageCache, IImageCacheFilePathOperation
{ {

View File

@@ -24,21 +24,31 @@ internal static class CoreEnvironment
/// </summary> /// </summary>
public const string HoyolabUA = $"Mozilla/5.0 (Windows NT 10.0; Win64; x64) miHoYoBBS/{HoyolabXrpcVersion}"; public const string HoyolabUA = $"Mozilla/5.0 (Windows NT 10.0; Win64; x64) miHoYoBBS/{HoyolabXrpcVersion}";
/// <summary>
/// Hoyolab请求UA
/// </summary>
public const string HoyolabOsUA = $"Mozilla/5.0 (Windows NT 10.0; Win64; x64) miHoYoBBSOversea/{HoyolabOsXrpcVersion}";
/// <summary> /// <summary>
/// 米游社移动端请求UA /// 米游社移动端请求UA
/// </summary> /// </summary>
public const string HoyolabMobileUA = $"Mozilla/5.0 (Linux; Android 12) Mobile miHoYoBBS/{HoyolabXrpcVersion}"; public const string HoyolabMobileUA = $"Mozilla/5.0 (Linux; Android 12) Mobile miHoYoBBS/{HoyolabXrpcVersion}";
/// <summary> /// <summary>
/// Hoyolab iPhone 移动端请求UA /// Hoyolab 移动端请求UA
/// </summary> /// </summary>
public const string HoyolabOsMobileUA = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBSOversea/2.28.0"; public const string HoyolabOsMobileUA = $"Mozilla/5.0 (Linux; Android 12) Mobile miHoYoBBSOversea/{HoyolabOsXrpcVersion}";
/// <summary> /// <summary>
/// 米游社 Rpc 版本 /// 米游社 Rpc 版本
/// </summary> /// </summary>
public const string HoyolabXrpcVersion = "2.44.1"; public const string HoyolabXrpcVersion = "2.44.1";
/// <summary>
/// Hoyolab Rpc 版本
/// </summary>
public const string HoyolabOsXrpcVersion = "2.28.0";
/// <summary> /// <summary>
/// 盐 /// 盐
/// </summary> /// </summary>
@@ -50,6 +60,8 @@ internal static class CoreEnvironment
[SaltType.X4] = "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs", [SaltType.X4] = "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs",
[SaltType.X6] = "t0qEgfub6cvueAPgR5m9aQWWVciEer7v", [SaltType.X6] = "t0qEgfub6cvueAPgR5m9aQWWVciEer7v",
[SaltType.PROD] = "JwYDpKvLj6MrMqqYU6jTKF17KNO2PXoS", [SaltType.PROD] = "JwYDpKvLj6MrMqqYU6jTKF17KNO2PXoS",
// This SALT is not reliable
[SaltType.OS] = "6cqshh5dhw73bzxn20oexa9k516chk7s", [SaltType.OS] = "6cqshh5dhw73bzxn20oexa9k516chk7s",
}.ToImmutableDictionary(); }.ToImmutableDictionary();

View File

@@ -15,7 +15,7 @@ internal sealed class HttpClientAttribute : Attribute
/// 构造一个新的特性 /// 构造一个新的特性
/// </summary> /// </summary>
/// <param name="configration">配置</param> /// <param name="configration">配置</param>
public HttpClientAttribute(HttpClientConfigration configration) public HttpClientAttribute(HttpClientConfiguration configration)
{ {
} }
} }

View File

@@ -7,7 +7,7 @@ namespace Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
/// Http客户端配置 /// Http客户端配置
/// </summary> /// </summary>
[HighQuality] [HighQuality]
internal enum HttpClientConfigration internal enum HttpClientConfiguration
{ {
/// <summary> /// <summary>
/// 默认配置 /// 默认配置

View File

@@ -12,6 +12,8 @@ namespace Snap.Hutao.Core.DependencyInjection;
[HighQuality] [HighQuality]
internal static partial class IocHttpClientConfiguration internal static partial class IocHttpClientConfiguration
{ {
private const string ApplicationJson = "application/json";
/// <summary> /// <summary>
/// 添加 <see cref="HttpClient"/> /// 添加 <see cref="HttpClient"/>
/// </summary> /// </summary>
@@ -37,7 +39,7 @@ internal static partial class IocHttpClientConfiguration
{ {
client.Timeout = Timeout.InfiniteTimeSpan; client.Timeout = Timeout.InfiniteTimeSpan;
client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreEnvironment.HoyolabUA); client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreEnvironment.HoyolabUA);
client.DefaultRequestHeaders.Accept.ParseAdd("application/json"); client.DefaultRequestHeaders.Accept.ParseAdd(ApplicationJson);
client.DefaultRequestHeaders.Add("x-rpc-app_version", CoreEnvironment.HoyolabXrpcVersion); client.DefaultRequestHeaders.Add("x-rpc-app_version", CoreEnvironment.HoyolabXrpcVersion);
client.DefaultRequestHeaders.Add("x-rpc-client_type", "5"); client.DefaultRequestHeaders.Add("x-rpc-client_type", "5");
client.DefaultRequestHeaders.Add("x-rpc-device_id", CoreEnvironment.HoyolabDeviceId); client.DefaultRequestHeaders.Add("x-rpc-device_id", CoreEnvironment.HoyolabDeviceId);
@@ -51,7 +53,7 @@ internal static partial class IocHttpClientConfiguration
{ {
client.Timeout = Timeout.InfiniteTimeSpan; client.Timeout = Timeout.InfiniteTimeSpan;
client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreEnvironment.HoyolabUA); client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreEnvironment.HoyolabUA);
client.DefaultRequestHeaders.Accept.ParseAdd("application/json"); client.DefaultRequestHeaders.Accept.ParseAdd(ApplicationJson);
client.DefaultRequestHeaders.Add("x-rpc-aigis", string.Empty); client.DefaultRequestHeaders.Add("x-rpc-aigis", string.Empty);
client.DefaultRequestHeaders.Add("x-rpc-app_id", "bll8iq97cem8"); client.DefaultRequestHeaders.Add("x-rpc-app_id", "bll8iq97cem8");
client.DefaultRequestHeaders.Add("x-rpc-app_version", CoreEnvironment.HoyolabXrpcVersion); client.DefaultRequestHeaders.Add("x-rpc-app_version", CoreEnvironment.HoyolabXrpcVersion);
@@ -69,8 +71,8 @@ internal static partial class IocHttpClientConfiguration
private static void XRpc3Configuration(HttpClient client) private static void XRpc3Configuration(HttpClient client)
{ {
client.Timeout = Timeout.InfiniteTimeSpan; client.Timeout = Timeout.InfiniteTimeSpan;
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"); client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreEnvironment.HoyolabOsUA);
client.DefaultRequestHeaders.Accept.ParseAdd("application/json"); client.DefaultRequestHeaders.Accept.ParseAdd(ApplicationJson);
client.DefaultRequestHeaders.Add("x-rpc-app_version", "1.5.0"); client.DefaultRequestHeaders.Add("x-rpc-app_version", "1.5.0");
client.DefaultRequestHeaders.Add("x-rpc-client_type", "4"); client.DefaultRequestHeaders.Add("x-rpc-client_type", "4");
} }

View File

@@ -4,7 +4,6 @@
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Snap.Hutao.Migrations;
using Snap.Hutao.Web.Hoyolab; using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.Bbs.User; using Snap.Hutao.Web.Hoyolab.Bbs.User;
using Snap.Hutao.Web.Hoyolab.Passport; using Snap.Hutao.Web.Hoyolab.Passport;
@@ -104,20 +103,13 @@ internal sealed class User : ObservableObject
internal static async Task<User> ResumeAsync(EntityUser inner, CancellationToken token = default) internal static async Task<User> ResumeAsync(EntityUser inner, CancellationToken token = default)
{ {
User user = new(inner); User user = new(inner);
bool isOk = false; bool isOk = user.Entity.IsOversea
? await user.InitializeCoreOsAsync(token).ConfigureAwait(false)
if (!user.Entity.IsOversea) : await user.InitializeCoreAsync(token).ConfigureAwait(false);
{
isOk = await user.InitializeCoreAsync(token).ConfigureAwait(false);
}
else
{
isOk = await user.InitializeCoreOsAsync(token).ConfigureAwait(false);
}
if (!isOk) if (!isOk)
{ {
user.UserInfo = new UserInfo() { Nickname = "网络异常" }; user.UserInfo = new() { Nickname = SH.ModelBindingUserInitializationFailed };
user.UserGameRoles = new(); user.UserGameRoles = new();
} }
@@ -137,7 +129,6 @@ internal sealed class User : ObservableObject
entity.Aid = cookie.GetValueOrDefault(Cookie.STUID); entity.Aid = cookie.GetValueOrDefault(Cookie.STUID);
entity.Mid = cookie.GetValueOrDefault(Cookie.MID); entity.Mid = cookie.GetValueOrDefault(Cookie.MID);
entity.IsOversea = false;
if (entity.Aid != null && entity.Mid != null) if (entity.Aid != null && entity.Mid != null)
{ {
@@ -153,20 +144,20 @@ internal sealed class User : ObservableObject
} }
/// <summary> /// <summary>
/// 创建并初始化国际服用户(临时) /// 创建并初始化国际服用户
/// </summary> /// </summary>
/// <param name="cookie">cookie</param> /// <param name="cookie">cookie</param>
/// <param name="token">取消令牌</param> /// <param name="token">取消令牌</param>
/// <returns>用户</returns> /// <returns>用户</returns>
internal static async Task<User?> CreateOsUserAsync(Cookie cookie, CancellationToken token = default) internal static async Task<User?> CreateOsAsync(Cookie cookie, CancellationToken token = default)
{ {
// 这里只负责创建实体用户,稍后在用户服务中保存到数据库 // 这里只负责创建实体用户,稍后在用户服务中保存到数据库
EntityUser entity = EntityUser.CreateOs(cookie); EntityUser entity = EntityUser.CreateOs(cookie);
entity.Aid = cookie.GetValueOrDefault(Cookie.STUID); entity.Aid = cookie.GetValueOrDefault(Cookie.STUID);
// Note: Currently we dont know how to get "mid" for hoyolab user, // Note: Currently we don't know how to get "mid" for hoyolab user,
// mid is set as the same value of ltuid(stuid/user id) // mid is set as the same value of ltuid/stuid
entity.Mid = entity.Aid; entity.Mid = entity.Aid;
entity.IsOversea = true; entity.IsOversea = true;
@@ -224,6 +215,88 @@ internal sealed class User : ObservableObject
return isInitialized = true; return isInitialized = true;
} }
private async Task<bool> InitializeCoreOsAsync(CancellationToken token = default)
{
if (isInitialized)
{
return true;
}
if (SToken == null)
{
return false;
}
using (IServiceScope scope = Ioc.Default.CreateScope())
{
// 自动填充 Ltoken
if (LToken == null)
{
Response<LtokenWrapper> ltokenResponse = await scope.ServiceProvider
.GetRequiredService<PassportClientOs>()
.GetLtokenBySTokenAsync(Entity, token)
.ConfigureAwait(false);
if (ltokenResponse.IsOk())
{
Cookie ltokenCookie = Cookie.Parse($"ltuid={Entity.Aid};ltoken={ltokenResponse.Data.Ltoken}");
Entity.LToken = ltokenCookie;
}
else
{
return false;
}
}
// Fetch user info
Response<UserFullInfoWrapper> response = await scope.ServiceProvider
.GetRequiredService<UserClient>()
.GetOsUserFullInfoAsync(Entity, token)
.ConfigureAwait(false);
UserInfo = response.Data?.UserInfo;
// 自动填充 CookieToken
if (CookieToken == null)
{
Response<UidCookieToken> cookieTokenResponse = await scope.ServiceProvider
.GetRequiredService<PassportClientOs>()
.GetCookieAccountInfoBySTokenAsync(Entity, token)
.ConfigureAwait(false);
if (cookieTokenResponse.IsOk())
{
Cookie cookieTokenCookie = Cookie.Parse($"account_id={Entity.Aid};cookie_token={cookieTokenResponse.Data.CookieToken}");
Entity.CookieToken = cookieTokenCookie;
}
else
{
return false;
}
}
// 获取游戏角色
Response<ListWrapper<UserGameRole>> userGameRolesResponse = await scope.ServiceProvider
.GetRequiredService<BindingClient>()
.GetOsUserGameRolesByCookieAsync(Entity, token)
.ConfigureAwait(false);
if (userGameRolesResponse.IsOk())
{
UserGameRoles = userGameRolesResponse.Data.List;
}
else
{
return false;
}
}
SelectedUserGameRole = UserGameRoles.FirstOrFirstOrDefault(role => role.IsChosen);
isInitialized = true;
return UserInfo != null && UserGameRoles.Any();
}
private async Task<bool> TrySetLTokenAsync(IServiceProvider provider, CancellationToken token) private async Task<bool> TrySetLTokenAsync(IServiceProvider provider, CancellationToken token)
{ {
if (LToken != null) if (LToken != null)
@@ -311,87 +384,4 @@ internal sealed class User : ObservableObject
return false; return false;
} }
} }
private async Task<bool> InitializeCoreOsAsync(CancellationToken token = default)
{
if (isInitialized)
{
return true;
}
if (SToken == null)
{
return false;
}
using (IServiceScope scope = Ioc.Default.CreateScope())
{
// 自动填充 Ltoken
if (LToken == null)
{
Response<LtokenWrapper> ltokenResponse = await scope.ServiceProvider
.GetRequiredService<PassportClientOs>()
.GetLtokenBySTokenAsync(Entity, token)
.ConfigureAwait(false);
if (ltokenResponse.IsOk())
{
Cookie ltokenCookie = Cookie.Parse($"ltuid={Entity.Aid};ltoken={ltokenResponse.Data.Ltoken}");
Entity.LToken = ltokenCookie;
}
else
{
return false;
}
}
// Fetch user info
Response<UserFullInfoWrapper> response = await scope.ServiceProvider
.GetRequiredService<UserClient>()
.GetOsUserFullInfoAsync(Entity, token)
.ConfigureAwait(false);
UserInfo = response.Data?.UserInfo;
// 自动填充 CookieToken
if (CookieToken == null)
{
Response<UidCookieToken> cookieTokenResponse = await scope.ServiceProvider
.GetRequiredService<PassportClientOs>()
.GetCookieAccountInfoBySTokenAsync(Entity, token)
.ConfigureAwait(false);
if (cookieTokenResponse.IsOk())
{
Cookie cookieTokenCookie = Cookie.Parse($"account_id={Entity.Aid};cookie_token={cookieTokenResponse.Data.CookieToken}");
Entity.CookieToken = cookieTokenCookie;
}
else
{
return false;
}
}
// 获取游戏角色
Response<ListWrapper<UserGameRole>> userGameRolesResponse = await scope.ServiceProvider
.GetRequiredService<BindingClient>()
.GetOsUserGameRolesByCookieAsync(Entity, token)
.ConfigureAwait(false);
if (userGameRolesResponse.IsOk())
{
UserGameRoles = userGameRolesResponse.Data.List;
}
else
{
return false;
}
}
SelectedUserGameRole = UserGameRoles.FirstOrFirstOrDefault(role => role.IsChosen);
isInitialized = true;
return UserInfo != null && UserGameRoles.Any();
}
} }

View File

@@ -81,7 +81,7 @@ internal sealed class User : ISelectable
/// <returns>新创建的用户</returns> /// <returns>新创建的用户</returns>
public static User CreateOs(Cookie cookie) public static User CreateOs(Cookie cookie)
{ {
_ = cookie.TryGetAsStokenV1(out Cookie? stoken); _ = cookie.TryGetAsLegacyStoken(out Cookie? stoken);
_ = cookie.TryGetAsLtoken(out Cookie? ltoken); _ = cookie.TryGetAsLtoken(out Cookie? ltoken);
_ = cookie.TryGetAsCookieToken(out Cookie? cookieToken); _ = cookie.TryGetAsCookieToken(out Cookie? cookieToken);

View File

@@ -411,6 +411,15 @@ namespace Snap.Hutao.Resource.Localization {
} }
} }
/// <summary>
/// 查找类似 网络异常 的本地化字符串。
/// </summary>
internal static string ModelBindingUserInitializationFailed {
get {
return ResourceManager.GetString("ModelBindingUserInitializationFailed", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 第 {0} 期 的本地化字符串。 /// 查找类似 第 {0} 期 的本地化字符串。
/// </summary> /// </summary>

View File

@@ -1806,4 +1806,7 @@
<data name="ViewServiceHutaoUserLoginOrRegisterHint" xml:space="preserve"> <data name="ViewServiceHutaoUserLoginOrRegisterHint" xml:space="preserve">
<value>立即登录或注册</value> <value>立即登录或注册</value>
</data> </data>
<data name="ModelBindingUserInitializationFailed" xml:space="preserve">
<value>网络异常</value>
</data>
</root> </root>

View File

@@ -16,7 +16,7 @@ namespace Snap.Hutao.Service.Game.Package;
/// 游戏文件包转换器 /// 游戏文件包转换器
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class PackageConverter internal sealed class PackageConverter
{ {
private readonly JsonSerializerOptions options; private readonly JsonSerializerOptions options;

View File

@@ -19,7 +19,7 @@ namespace Snap.Hutao.Service.Metadata;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[Injection(InjectAs.Singleton, typeof(IMetadataService))] [Injection(InjectAs.Singleton, typeof(IMetadataService))]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed partial class MetadataService : IMetadataService, IMetadataServiceInitialization internal sealed partial class MetadataService : IMetadataService, IMetadataServiceInitialization
{ {
private const string MetaFileName = "Meta.json"; private const string MetaFileName = "Meta.json";

View File

@@ -329,7 +329,7 @@ internal class UserService : IUserService
// 判断是否为国际服 // 判断是否为国际服
if (isOversea) if (isOversea)
{ {
newUser = await BindingUser.CreateOsUserAsync(cookie).ConfigureAwait(false); newUser = await BindingUser.CreateOsAsync(cookie).ConfigureAwait(false);
} }
else else
{ {

View File

@@ -49,7 +49,7 @@ internal sealed partial class SignInWebViewDialog : ContentDialog
if (user.Entity.IsOversea) if (user.Entity.IsOversea)
{ {
coreWebView2.SetCookie(user.CookieToken, user.LToken, null).SetOsMobileUserAgent(); coreWebView2.SetCookie(user.CookieToken, user.LToken, null).SetMobileOsUserAgent();
signInJsInterface = new(coreWebView2, scope.ServiceProvider); signInJsInterface = new(coreWebView2, scope.ServiceProvider);
coreWebView2.Navigate("https://act.hoyolab.com/ys/event/signin-sea-v3/index.html?act_id=e202102251931481&hyl_presentation_style=fullscreen"); coreWebView2.Navigate("https://act.hoyolab.com/ys/event/signin-sea-v3/index.html?act_id=e202102251931481&hyl_presentation_style=fullscreen");
} }

View File

@@ -24,11 +24,11 @@ internal static class CoreWebView2Extension
} }
/// <summary> /// <summary>
/// 设置 移动端UA /// 设置 移动端OsUA
/// </summary> /// </summary>
/// <param name="webView">webview2</param> /// <param name="webView">webview2</param>
/// <returns>链式调用的WebView2</returns> /// <returns>链式调用的WebView2</returns>
public static CoreWebView2 SetOsMobileUserAgent(this CoreWebView2 webView) public static CoreWebView2 SetMobileOsUserAgent(this CoreWebView2 webView)
{ {
webView.Settings.UserAgent = Core.CoreEnvironment.HoyolabOsMobileUA; webView.Settings.UserAgent = Core.CoreEnvironment.HoyolabOsMobileUA;
return webView; return webView;

View File

@@ -12,7 +12,7 @@ namespace Snap.Hutao.Web.Enka;
/// Enka API 客户端 /// Enka API 客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class EnkaClient internal sealed class EnkaClient
{ {
private const string EnkaAPI = "https://enka.network/api/uid/{0}"; private const string EnkaAPI = "https://enka.network/api/uid/{0}";

View File

@@ -11,7 +11,7 @@ namespace Snap.Hutao.Web.Geetest;
/// 极验客户端 /// 极验客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class GeetestClient internal sealed class GeetestClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -16,7 +16,7 @@ namespace Snap.Hutao.Web.Hoyolab.App.Account;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret] [UseDynamicSecret]
[HttpClient(HttpClientConfigration.XRpc)] [HttpClient(HttpClientConfiguration.XRpc)]
internal sealed class AccountClient internal sealed class AccountClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -14,7 +14,7 @@ namespace Snap.Hutao.Web.Hoyolab.Bbs.User;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret] [UseDynamicSecret]
[HttpClient(HttpClientConfigration.XRpc)] [HttpClient(HttpClientConfiguration.XRpc)]
internal sealed class UserClient internal sealed class UserClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -122,7 +122,7 @@ internal sealed partial class Cookie
/// </summary> /// </summary>
/// <param name="cookie">A cookie contains stoken and stuid, without mid.</param> /// <param name="cookie">A cookie contains stoken and stuid, without mid.</param>
/// <returns>是否获取成功</returns> /// <returns>是否获取成功</returns>
public bool TryGetAsStokenV1([NotNullWhen(true)] out Cookie? cookie) public bool TryGetAsLegacyStoken([NotNullWhen(true)] out Cookie? cookie)
{ {
bool hasStoken = TryGetValue(STOKEN, out string? stoken); bool hasStoken = TryGetValue(STOKEN, out string? stoken);
bool hasStuid = TryGetValue(STUID, out string? stuid); bool hasStuid = TryGetValue(STUID, out string? stuid);

View File

@@ -10,7 +10,7 @@ namespace Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement;
/// <summary> /// <summary>
/// 公告客户端 /// 公告客户端
/// </summary> /// </summary>
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class AnnouncementClient internal sealed class AnnouncementClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -11,7 +11,7 @@ namespace Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
/// 祈愿记录客户端 /// 祈愿记录客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class GachaInfoClient internal sealed class GachaInfoClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -13,7 +13,7 @@ namespace Snap.Hutao.Web.Hoyolab.Passport;
/// 通行证客户端 /// 通行证客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class PassportClient internal sealed class PassportClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -16,7 +16,7 @@ namespace Snap.Hutao.Web.Hoyolab.Passport;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret] [UseDynamicSecret]
[HttpClient(HttpClientConfigration.XRpc2)] [HttpClient(HttpClientConfiguration.XRpc2)]
internal sealed class PassportClient2 internal sealed class PassportClient2
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -14,7 +14,7 @@ namespace Snap.Hutao.Web.Hoyolab.Passport;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret] [UseDynamicSecret]
[HttpClient(HttpClientConfigration.XRpc3)] [HttpClient(HttpClientConfiguration.XRpc3)]
internal sealed class PassportClientOs internal sealed class PassportClientOs
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -12,7 +12,7 @@ namespace Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher;
/// 游戏资源客户端 /// 游戏资源客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class ResourceClient internal sealed class ResourceClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -16,7 +16,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.Auth;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret] [UseDynamicSecret]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class AuthClient internal sealed class AuthClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -13,7 +13,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.Auth;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret] [UseDynamicSecret]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class AuthClientOs internal sealed class AuthClientOs
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -13,7 +13,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.Binding;
/// 绑定客户端 /// 绑定客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class BindingClient internal sealed class BindingClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -15,7 +15,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.Binding;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret] [UseDynamicSecret]
[HttpClient(HttpClientConfigration.XRpc)] [HttpClient(HttpClientConfiguration.XRpc)]
internal sealed class BindingClient2 internal sealed class BindingClient2
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -13,7 +13,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
/// 养成计算器客户端 /// 养成计算器客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class CalculateClient internal sealed class CalculateClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -16,7 +16,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret] [UseDynamicSecret]
[HttpClient(HttpClientConfigration.XRpc)] [HttpClient(HttpClientConfiguration.XRpc)]
internal sealed class CardClient internal sealed class CardClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -18,7 +18,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret] [UseDynamicSecret]
[HttpClient(HttpClientConfigration.XRpc)] [HttpClient(HttpClientConfiguration.XRpc)]
[PrimaryHttpMessageHandler(UseCookies = false)] [PrimaryHttpMessageHandler(UseCookies = false)]
internal sealed class GameRecordClient internal sealed class GameRecordClient
{ {

View File

@@ -15,7 +15,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[UseDynamicSecret] [UseDynamicSecret]
[HttpClient(HttpClientConfigration.XRpc3)] [HttpClient(HttpClientConfiguration.XRpc3)]
[PrimaryHttpMessageHandler(UseCookies = false)] [PrimaryHttpMessageHandler(UseCookies = false)]
internal sealed class GameRecordClientOs internal sealed class GameRecordClientOs
{ {

View File

@@ -12,7 +12,7 @@ namespace Snap.Hutao.Web.Hutao;
/// 胡桃日志客户端 /// 胡桃日志客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class HomaLogUploadClient internal sealed class HomaLogUploadClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;

View File

@@ -13,7 +13,7 @@ namespace Snap.Hutao.Web.Hutao;
/// 胡桃通行证客户端 /// 胡桃通行证客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class HomaPassportClient internal sealed class HomaPassportClient
{ {
/// <summary> /// <summary>

View File

@@ -18,7 +18,7 @@ namespace Snap.Hutao.Web.Hutao;
/// 胡桃API客户端 /// 胡桃API客户端
/// </summary> /// </summary>
[HighQuality] [HighQuality]
[HttpClient(HttpClientConfigration.Default)] [HttpClient(HttpClientConfiguration.Default)]
internal sealed class HomaSpiralAbyssClient internal sealed class HomaSpiralAbyssClient
{ {
private readonly HttpClient httpClient; private readonly HttpClient httpClient;