mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Really fast
This commit is contained in:
@@ -105,6 +105,7 @@ internal sealed class ConstructorGenerator : IIncrementalGenerator
|
||||
|
||||
foreach (IFieldSymbol fieldSymbol in fields)
|
||||
{
|
||||
if(fieldSymbol.Kind == SymbolKind.Field)
|
||||
if (fieldSymbol.IsReadOnly && !fieldSymbol.IsStatic)
|
||||
{
|
||||
switch (fieldSymbol.Type.ToDisplayString())
|
||||
|
||||
@@ -17,6 +17,7 @@ internal static class SelectableExtension
|
||||
/// <typeparam name="TSource">源类型</typeparam>
|
||||
/// <param name="source">源</param>
|
||||
/// <returns>选中的值或默认值</returns>
|
||||
/// <exception cref="InvalidOperationException">存在多个选中的值</exception>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static TSource? SelectedOrDefault<TSource>(this IEnumerable<TSource> source)
|
||||
where TSource : ISelectable
|
||||
|
||||
@@ -105,6 +105,30 @@ internal static partial class EnumerableExtension
|
||||
return results;
|
||||
}
|
||||
|
||||
public static async ValueTask<List<TResult>> SelectListAsync<TSource, TResult>(this List<TSource> list, Func<TSource, ValueTask<TResult>> selector)
|
||||
{
|
||||
List<TResult> results = new(list.Count);
|
||||
|
||||
foreach (TSource item in list)
|
||||
{
|
||||
results.Add(await selector(item).ConfigureAwait(false));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public static async ValueTask<List<TResult>> SelectListAsync<TSource, TResult>(this List<TSource> list, Func<TSource, CancellationToken, ValueTask<TResult>> selector, CancellationToken token)
|
||||
{
|
||||
List<TResult> results = new(list.Count);
|
||||
|
||||
foreach (TSource item in list)
|
||||
{
|
||||
results.Add(await selector(item, token).ConfigureAwait(false));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||
public static List<TSource> SortBy<TSource, TKey>(this List<TSource> list, Func<TSource, TKey> keySelector)
|
||||
where TKey : IComparable
|
||||
|
||||
@@ -83,9 +83,9 @@ internal sealed partial class AnnouncementService : IAnnouncementService
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 匹配特殊的时间格式: <t>(.*?)</t>
|
||||
/// 匹配特殊的时间格式: <t.*?>(.*?)</t>
|
||||
/// </summary>
|
||||
/// <returns>正则</returns>
|
||||
[GeneratedRegex("<t.*?>(.*?)</t>", RegexOptions.Multiline)]
|
||||
[GeneratedRegex("<t class=\"t_gl\".*?>(.*?)</t>", RegexOptions.Multiline)]
|
||||
private static partial Regex XmlTagRegex();
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Snap.Hutao.Service;
|
||||
/// 存储服务相关的选项
|
||||
/// </summary>
|
||||
[Injection(InjectAs.Singleton)]
|
||||
internal sealed class AppOptions : DbStoreOptions
|
||||
internal sealed partial class AppOptions : DbStoreOptions
|
||||
{
|
||||
private readonly List<NameValue<BackdropType>> supportedBackdropTypes = new()
|
||||
{
|
||||
|
||||
@@ -24,8 +24,6 @@ namespace Snap.Hutao.Service.Game.Package;
|
||||
internal sealed partial class PackageConverter
|
||||
{
|
||||
private const string PackageVersion = "pkg_version";
|
||||
private const string OverseaFolder = "Oversea";
|
||||
private const string ChineseFolder = "Chinese";
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly JsonSerializerOptions options;
|
||||
private readonly RuntimeOptions runtimeOptions;
|
||||
|
||||
@@ -17,6 +17,7 @@ internal sealed class PackageReplaceStatus : ICloneable<PackageReplaceStatus>
|
||||
/// <param name="description">描述</param>
|
||||
public PackageReplaceStatus(string description)
|
||||
{
|
||||
Name = default!;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
|
||||
15
src/Snap.Hutao/Snap.Hutao/Service/User/IUserDbService.cs
Normal file
15
src/Snap.Hutao/Snap.Hutao/Service/User/IUserDbService.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.User;
|
||||
|
||||
internal interface IUserDbService
|
||||
{
|
||||
ValueTask AddUserAsync(Model.Entity.User user);
|
||||
|
||||
ValueTask DeleteUserByIdAsync(Guid id);
|
||||
|
||||
ValueTask<List<Model.Entity.User>> GetUserListAsync();
|
||||
|
||||
ValueTask UpdateUserAsync(Model.Entity.User user);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ internal interface IUserService
|
||||
/// 异步获取角色与用户集合
|
||||
/// </summary>
|
||||
/// <returns>角色与用户集合</returns>
|
||||
Task<ObservableCollection<UserAndUid>> GetRoleCollectionAsync();
|
||||
ValueTask<ObservableCollection<UserAndUid>> GetRoleCollectionAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 初始化用户服务及所有用户
|
||||
@@ -48,14 +48,14 @@ internal interface IUserService
|
||||
/// <param name="cookie">Cookie</param>
|
||||
/// <param name="isOversea">是否为国际服</param>
|
||||
/// <returns>处理的结果</returns>
|
||||
Task<ValueResult<UserOptionResult, string>> ProcessInputCookieAsync(Cookie cookie, bool isOversea);
|
||||
ValueTask<ValueResult<UserOptionResult, string>> ProcessInputCookieAsync(Cookie cookie, bool isOversea);
|
||||
|
||||
/// <summary>
|
||||
/// 异步刷新 Cookie 的 CookieToken
|
||||
/// </summary>
|
||||
/// <param name="user">用户</param>
|
||||
/// <returns>是否刷新成功</returns>
|
||||
Task<bool> RefreshCookieTokenAsync(BindingUser user);
|
||||
ValueTask<bool> RefreshCookieTokenAsync(BindingUser user);
|
||||
|
||||
/// <summary>
|
||||
/// 异步移除用户
|
||||
|
||||
62
src/Snap.Hutao/Snap.Hutao/Service/User/UserDbService.cs
Normal file
62
src/Snap.Hutao/Snap.Hutao/Service/User/UserDbService.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.DependencyInjection.Abstraction;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Message;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Snap.Hutao.ViewModel.User;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
using Snap.Hutao.Web.Hoyolab.Passport;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using System.Collections.ObjectModel;
|
||||
using BindingUser = Snap.Hutao.ViewModel.User.User;
|
||||
|
||||
namespace Snap.Hutao.Service.User;
|
||||
|
||||
[ConstructorGenerated]
|
||||
[Injection(InjectAs.Singleton, typeof(IUserDbService))]
|
||||
internal sealed partial class UserDbService : IUserDbService
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
|
||||
public async ValueTask DeleteUserByIdAsync(Guid id)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.Users.ExecuteDeleteWhereAsync(u => u.InnerId == id).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask<List<Model.Entity.User>> GetUserListAsync()
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
return await appDbContext.Users.AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask UpdateUserAsync(Model.Entity.User user)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.Users.UpdateAndSaveAsync(user).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask AddUserAsync(Model.Entity.User user)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.Users.AddAndSaveAsync(user).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.DependencyInjection.Abstraction;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
@@ -61,23 +62,13 @@ internal sealed partial class UserService : IUserService
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
if (userCollection == null)
|
||||
{
|
||||
List<BindingUser> users = new();
|
||||
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
|
||||
foreach (Model.Entity.User entity in appDbContext.Users)
|
||||
{
|
||||
BindingUser initialized = await BindingUser.ResumeAsync(entity).ConfigureAwait(false);
|
||||
users.Add(initialized);
|
||||
}
|
||||
}
|
||||
|
||||
List<Model.Entity.User> entities = await userDbService.GetUserListAsync().ConfigureAwait(false);
|
||||
List<BindingUser> users = await entities.SelectListAsync(BindingUser.ResumeAsync, default).ConfigureAwait(false);
|
||||
userCollection = users.ToObservableCollection();
|
||||
|
||||
try
|
||||
{
|
||||
Current = users.SingleOrDefault(user => user.IsSelected);
|
||||
Current = users.SelectedOrDefault();
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
@@ -89,22 +80,15 @@ internal sealed partial class UserService : IUserService
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<ObservableCollection<UserAndUid>> GetRoleCollectionAsync()
|
||||
public async ValueTask<ObservableCollection<UserAndUid>> GetRoleCollectionAsync()
|
||||
{
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
if (userAndUidCollection == null)
|
||||
{
|
||||
List<UserAndUid> userAndUids = new();
|
||||
ObservableCollection<BindingUser> observableUsers = await GetUserCollectionAsync().ConfigureAwait(false);
|
||||
foreach (BindingUser user in observableUsers)
|
||||
{
|
||||
foreach (UserGameRole role in user.UserGameRoles)
|
||||
{
|
||||
userAndUids.Add(new(user.Entity, role));
|
||||
}
|
||||
}
|
||||
|
||||
userAndUidCollection = userAndUids.ToObservableCollection();
|
||||
ObservableCollection<BindingUser> users = await GetUserCollectionAsync().ConfigureAwait(false);
|
||||
userAndUidCollection = users
|
||||
.SelectMany(user => user.UserGameRoles.Select(role => UserAndUid.From(user.Entity, role)))
|
||||
.ToObservableCollection();
|
||||
}
|
||||
|
||||
return userAndUidCollection;
|
||||
@@ -113,11 +97,10 @@ internal sealed partial class UserService : IUserService
|
||||
/// <inheritdoc/>
|
||||
public UserGameRole? GetUserGameRoleByUid(string uid)
|
||||
{
|
||||
if (userCollection != null)
|
||||
if (userCollection is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: optimize match speed.
|
||||
return userCollection.SelectMany(u => u.UserGameRoles).SingleOrDefault(r => r.GameUid == uid);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
@@ -127,16 +110,16 @@ internal sealed partial class UserService : IUserService
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<ValueResult<UserOptionResult, string>> ProcessInputCookieAsync(Cookie cookie, bool isOversea)
|
||||
public async ValueTask<ValueResult<UserOptionResult, string>> ProcessInputCookieAsync(Cookie cookie, bool isOversea)
|
||||
{
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
string? mid = cookie.GetValueOrDefault(isOversea ? Cookie.STUID : Cookie.MID);
|
||||
|
||||
if (mid == null)
|
||||
if (string.IsNullOrEmpty(mid))
|
||||
{
|
||||
return new(UserOptionResult.Invalid, SH.ServiceUserProcessCookieNoMid);
|
||||
}
|
||||
@@ -144,23 +127,18 @@ internal sealed partial class UserService : IUserService
|
||||
// 检查 mid 对应用户是否存在
|
||||
if (TryGetUser(userCollection!, mid, out BindingUser? user))
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
if (cookie.TryGetSToken(isOversea, out Cookie? stoken))
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
user.SToken = stoken;
|
||||
user.LToken = cookie.TryGetLToken(out Cookie? ltoken) ? ltoken : user.LToken;
|
||||
user.CookieToken = cookie.TryGetCookieToken(out Cookie? cookieToken) ? cookieToken : user.CookieToken;
|
||||
|
||||
if (cookie.TryGetSToken(isOversea, out Cookie? stoken))
|
||||
{
|
||||
user.SToken = stoken;
|
||||
user.LToken = cookie.TryGetLToken(out Cookie? ltoken) ? ltoken : user.LToken;
|
||||
user.CookieToken = cookie.TryGetCookieToken(out Cookie? cookieToken) ? cookieToken : user.CookieToken;
|
||||
|
||||
await appDbContext.Users.UpdateAndSaveAsync(user.Entity).ConfigureAwait(false);
|
||||
return new(UserOptionResult.Updated, mid);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new(UserOptionResult.Invalid, SH.ServiceUserProcessCookieNoSToken);
|
||||
}
|
||||
await userDbService.UpdateUserAsync(user.Entity).ConfigureAwait(false);
|
||||
return new(UserOptionResult.Updated, mid);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new(UserOptionResult.Invalid, SH.ServiceUserProcessCookieNoSToken);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -170,99 +148,71 @@ internal sealed partial class UserService : IUserService
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<bool> RefreshCookieTokenAsync(BindingUser user)
|
||||
public async ValueTask<bool> RefreshCookieTokenAsync(BindingUser user)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
Response<UidCookieToken> cookieTokenResponse = await serviceProvider
|
||||
.GetRequiredService<IOverseaSupportFactory<IPassportClient>>()
|
||||
.Create(user.Entity.IsOversea)
|
||||
.GetCookieAccountInfoBySTokenAsync(user.Entity)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (cookieTokenResponse.IsOk())
|
||||
{
|
||||
Response<UidCookieToken> cookieTokenResponse = await scope.ServiceProvider
|
||||
.GetRequiredService<IOverseaSupportFactory<IPassportClient>>()
|
||||
.Create(user.Entity.IsOversea)
|
||||
.GetCookieAccountInfoBySTokenAsync(user.Entity)
|
||||
.ConfigureAwait(false);
|
||||
string cookieToken = cookieTokenResponse.Data.CookieToken;
|
||||
|
||||
if (cookieTokenResponse.IsOk())
|
||||
{
|
||||
string cookieToken = cookieTokenResponse.Data.CookieToken;
|
||||
// Check null and create a new one to avoid System.NullReferenceException
|
||||
user.CookieToken ??= new();
|
||||
|
||||
// Check null and create a new one to avoid System.NullReferenceException
|
||||
user.CookieToken ??= new();
|
||||
// Sync ui and database
|
||||
user.CookieToken[Cookie.COOKIE_TOKEN] = cookieToken!;
|
||||
await userDbService.UpdateUserAsync(user.Entity).ConfigureAwait(false);
|
||||
|
||||
// sync ui and database
|
||||
user.CookieToken[Cookie.COOKIE_TOKEN] = cookieToken!;
|
||||
scope.ServiceProvider.GetRequiredService<AppDbContext>().Users.UpdateAndSave(user.Entity);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryGetUser(ObservableCollection<BindingUser> users, string mid, [NotNullWhen(true)] out BindingUser? user)
|
||||
{
|
||||
user = users.SingleOrDefault(u => u.Entity.Mid == mid);
|
||||
return user != null;
|
||||
return user is not null;
|
||||
}
|
||||
|
||||
private async Task<ValueResult<UserOptionResult, string>> TryCreateUserAndAddAsync(Cookie cookie, bool isOversea)
|
||||
private async ValueTask<ValueResult<UserOptionResult, string>> TryCreateUserAndAddAsync(Cookie cookie, bool isOversea)
|
||||
{
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
BindingUser? newUser = await BindingUser.CreateAsync(cookie, isOversea).ConfigureAwait(false);
|
||||
|
||||
if (newUser != null)
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
BindingUser? newUser = await BindingUser.CreateAsync(cookie, isOversea).ConfigureAwait(false);
|
||||
|
||||
if (newUser != null)
|
||||
// Sync cache
|
||||
if (userCollection != null)
|
||||
{
|
||||
// Sync cache
|
||||
if (userCollection != null)
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
{
|
||||
userCollection!.Add(newUser);
|
||||
userCollection!.Add(newUser);
|
||||
|
||||
if (userAndUidCollection != null)
|
||||
if (userAndUidCollection != null)
|
||||
{
|
||||
foreach (UserGameRole role in newUser.UserGameRoles)
|
||||
{
|
||||
foreach (UserGameRole role in newUser.UserGameRoles)
|
||||
{
|
||||
userAndUidCollection.Add(new(newUser.Entity, role));
|
||||
}
|
||||
userAndUidCollection.Add(new(newUser.Entity, role));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sync database
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
await appDbContext.Users.AddAndSaveAsync(newUser.Entity).ConfigureAwait(false);
|
||||
return new(UserOptionResult.Added, newUser.UserInfo!.Uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new(UserOptionResult.Invalid, SH.ServiceUserProcessCookieRequestUserInfoFailed);
|
||||
}
|
||||
// Sync database
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
await userDbService.AddUserAsync(newUser.Entity).ConfigureAwait(false);
|
||||
return new(UserOptionResult.Added, newUser.UserInfo!.Uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ConstructorGenerated]
|
||||
[Injection(InjectAs.Singleton, typeof(IUserDbService))]
|
||||
internal sealed partial class UserDbService : IUserDbService
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
|
||||
public async ValueTask DeleteUserByIdAsync(Guid id)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
else
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.Users.ExecuteDeleteWhereAsync(u => u.InnerId == id).ConfigureAwait(false);
|
||||
return new(UserOptionResult.Invalid, SH.ServiceUserProcessCookieRequestUserInfoFailed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal interface IUserDbService
|
||||
{
|
||||
ValueTask DeleteUserByIdAsync(Guid id);
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.DependencyInjection.Abstraction;
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
@@ -18,7 +19,7 @@ namespace Snap.Hutao.ViewModel.User;
|
||||
/// 用于视图绑定的用户
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class User : ObservableObject, IEntityOnly<EntityUser>
|
||||
internal sealed class User : ObservableObject, IEntityOnly<EntityUser>, ISelectable
|
||||
{
|
||||
private readonly EntityUser inner;
|
||||
|
||||
@@ -61,6 +62,8 @@ internal sealed class User : ObservableObject, IEntityOnly<EntityUser>
|
||||
}
|
||||
}
|
||||
|
||||
public Guid InnerId { get => inner.InnerId; }
|
||||
|
||||
/// <inheritdoc cref="EntityUser.IsSelected"/>
|
||||
public bool IsSelected
|
||||
{
|
||||
@@ -105,7 +108,7 @@ internal sealed class User : ObservableObject, IEntityOnly<EntityUser>
|
||||
/// <param name="inner">数据库实体</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>用户</returns>
|
||||
internal static async Task<User> ResumeAsync(EntityUser inner, CancellationToken token = default)
|
||||
internal static async ValueTask<User> ResumeAsync(EntityUser inner, CancellationToken token = default)
|
||||
{
|
||||
User user = new(inner);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Abstraction;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
using EntityUser = Snap.Hutao.Model.Entity.User;
|
||||
|
||||
@@ -12,7 +13,7 @@ namespace Snap.Hutao.ViewModel.User;
|
||||
/// 抽象此类用于简化这类调用
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class UserAndUid
|
||||
internal sealed class UserAndUid : IMappingFrom<UserAndUid, EntityUser, PlayerUid>
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的实体用户与角色
|
||||
@@ -35,6 +36,11 @@ internal sealed class UserAndUid
|
||||
/// </summary>
|
||||
public PlayerUid Uid { get; private set; }
|
||||
|
||||
public static UserAndUid From(EntityUser user, PlayerUid role)
|
||||
{
|
||||
return new(user, role);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试转换到用户与角色
|
||||
/// </summary>
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Snap.Hutao.Web.Hoyolab.Bbs.User;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[UseDynamicSecret]
|
||||
[ConstructorGenerated]
|
||||
[ConstructorGenerated(ResolveHttpClient = true)]
|
||||
[HttpClient(HttpClientConfiguration.XRpc)]
|
||||
internal sealed partial class UserClient : IUserClient
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ using Snap.Hutao.Core.DependencyInjection.Abstraction;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Bbs.User;
|
||||
|
||||
[Injection(InjectAs.Transient)]
|
||||
[Injection(InjectAs.Transient, typeof(IOverseaSupportFactory<IUserClient>))]
|
||||
[ConstructorGenerated(CallBaseConstructor = true)]
|
||||
internal sealed partial class UserClientFactory : OverseaSupportFactory<IUserClient, UserClient, UserClientOversea>
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Snap.Hutao.Web.Hoyolab.Bbs.User;
|
||||
/// 用户信息客户端 Hoyolab版
|
||||
/// </summary>
|
||||
[UseDynamicSecret]
|
||||
[ConstructorGenerated]
|
||||
[ConstructorGenerated(ResolveHttpClient = true)]
|
||||
[HttpClient(HttpClientConfiguration.Default)]
|
||||
internal sealed partial class UserClientOversea : IUserClient
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[UseDynamicSecret]
|
||||
[ConstructorGenerated]
|
||||
[ConstructorGenerated(ResolveHttpClient = true)]
|
||||
[HttpClient(HttpClientConfiguration.XRpc)]
|
||||
[PrimaryHttpMessageHandler(UseCookies = false)]
|
||||
internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
|
||||
/// Hoyoverse game record provider
|
||||
/// </summary>
|
||||
[UseDynamicSecret]
|
||||
[ConstructorGenerated]
|
||||
[ConstructorGenerated(ResolveHttpClient = true)]
|
||||
[HttpClient(HttpClientConfiguration.XRpc3)]
|
||||
[PrimaryHttpMessageHandler(UseCookies = false)]
|
||||
internal sealed partial class GameRecordClientOversea : IGameRecordClient
|
||||
|
||||
Reference in New Issue
Block a user