mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
refactor done
This commit is contained in:
@@ -49,15 +49,14 @@ internal static partial class EnumerableExtension
|
||||
return list.GetRange(start, length);
|
||||
}
|
||||
|
||||
public static bool IsNullOrEmpty<TSource>([NotNullWhen(false)] this List<TSource>? source)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNullOrEmpty<TSource>([NotNullWhen(false)][MaybeNullWhen(true)] this List<TSource>? source)
|
||||
{
|
||||
if (source is { } list)
|
||||
if (source is { Count: > 0 })
|
||||
{
|
||||
// empty
|
||||
return list.Count <= 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// null
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ internal sealed partial class LaunchGameViewModel : Abstraction.ViewModel
|
||||
/// <summary>
|
||||
/// 已知的服务器方案
|
||||
/// </summary>
|
||||
[SuppressMessage("", "CA1822")]
|
||||
public List<LaunchScheme> KnownSchemes { get => LaunchScheme.GetKnownSchemes(); }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -417,7 +417,8 @@ internal class MiHoYoJSInterface
|
||||
private void OnNavigationStarting(CoreWebView2 coreWebView2, CoreWebView2NavigationStartingEventArgs args)
|
||||
{
|
||||
string uriHost = new Uri(args.Uri).Host;
|
||||
if (uriHost.EndsWith("mihoyo.com") || uriHost.EndsWith("hoyolab.com"))
|
||||
ReadOnlySpan<char> uriHostSpan = uriHost.AsSpan();
|
||||
if (uriHostSpan.EndsWith("mihoyo.com") || uriHostSpan.EndsWith("hoyolab.com"))
|
||||
{
|
||||
// Execute this solve issue: When open same site second time,there might be no bridge init.
|
||||
coreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(InitializeJsInterfaceScript2).AsTask().SafeForget(logger);
|
||||
|
||||
@@ -34,7 +34,7 @@ internal sealed partial class EnkaClient
|
||||
/// <returns>Enka API 响应</returns>
|
||||
public ValueTask<EnkaResponse?> GetForwardDataAsync(in PlayerUid playerUid, CancellationToken token = default)
|
||||
{
|
||||
return TryGetEnkaResponseCoreAsync(string.Format(EnkaAPIHutaoForward, playerUid.Value), token);
|
||||
return TryGetEnkaResponseCoreAsync(EnkaAPIHutaoForward.Format(playerUid.Value), token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -45,7 +45,7 @@ internal sealed partial class Cookie
|
||||
public static Cookie Parse(string cookieString)
|
||||
{
|
||||
SortedDictionary<string, string> cookieMap = new();
|
||||
cookieString = cookieString.Replace(" ", string.Empty);
|
||||
cookieString = cookieString.Replace(" ", string.Empty, StringComparison.Ordinal);
|
||||
string[] values = cookieString.Split(';', StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (string[] parts in values.Select(c => c.Split('=', 2)))
|
||||
{
|
||||
@@ -76,7 +76,7 @@ internal sealed partial class Cookie
|
||||
/// <returns>Cookie</returns>
|
||||
public static Cookie FromLoginResult(LoginResult? loginResult)
|
||||
{
|
||||
if (loginResult == null)
|
||||
if (loginResult is null)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
@@ -115,15 +115,12 @@ internal sealed partial class Cookie
|
||||
|
||||
public bool TryGetLToken([NotNullWhen(true)] out Cookie? cookie)
|
||||
{
|
||||
bool hasLtoken = TryGetValue(LTOKEN, out string? ltoken);
|
||||
bool hasStuid = TryGetValue(LTUID, out string? ltuid);
|
||||
|
||||
if (hasLtoken && hasStuid)
|
||||
if (TryGetValue(LTOKEN, out string? ltoken) && TryGetValue(LTUID, out string? ltuid))
|
||||
{
|
||||
cookie = new Cookie(new()
|
||||
{
|
||||
[LTOKEN] = ltoken!,
|
||||
[LTUID] = ltuid!,
|
||||
[LTOKEN] = ltoken,
|
||||
[LTUID] = ltuid,
|
||||
});
|
||||
|
||||
return true;
|
||||
@@ -135,15 +132,12 @@ internal sealed partial class Cookie
|
||||
|
||||
public bool TryGetCookieToken([NotNullWhen(true)] out Cookie? cookie)
|
||||
{
|
||||
bool hasAccountId = TryGetValue(ACCOUNT_ID, out string? accountId);
|
||||
bool hasCookieToken = TryGetValue(COOKIE_TOKEN, out string? cookieToken);
|
||||
|
||||
if (hasAccountId && hasCookieToken)
|
||||
if (TryGetValue(ACCOUNT_ID, out string? accountId) && TryGetValue(COOKIE_TOKEN, out string? cookieToken))
|
||||
{
|
||||
cookie = new Cookie(new()
|
||||
{
|
||||
[ACCOUNT_ID] = accountId!,
|
||||
[COOKIE_TOKEN] = cookieToken!,
|
||||
[ACCOUNT_ID] = accountId,
|
||||
[COOKIE_TOKEN] = cookieToken,
|
||||
});
|
||||
|
||||
return true;
|
||||
@@ -180,17 +174,13 @@ internal sealed partial class Cookie
|
||||
|
||||
private bool TryGetSToken([NotNullWhen(true)] out Cookie? cookie)
|
||||
{
|
||||
bool hasMid = TryGetValue(MID, out string? mid);
|
||||
bool hasSToken = TryGetValue(STOKEN, out string? stoken);
|
||||
bool hasSTuid = TryGetValue(STUID, out string? stuid);
|
||||
|
||||
if (hasMid && hasSToken && hasSTuid)
|
||||
if (TryGetValue(MID, out string? mid) && TryGetValue(STOKEN, out string? stoken) && TryGetValue(STUID, out string? stuid))
|
||||
{
|
||||
cookie = new Cookie(new()
|
||||
{
|
||||
[MID] = mid!,
|
||||
[STOKEN] = stoken!,
|
||||
[STUID] = stuid!,
|
||||
[MID] = mid,
|
||||
[STOKEN] = stoken,
|
||||
[STUID] = stuid,
|
||||
});
|
||||
|
||||
return true;
|
||||
@@ -202,15 +192,12 @@ internal sealed partial class Cookie
|
||||
|
||||
private bool TryGetLegacySToken([NotNullWhen(true)] out Cookie? cookie)
|
||||
{
|
||||
bool hasSToken = TryGetValue(STOKEN, out string? stoken);
|
||||
bool hasSTuid = TryGetValue(STUID, out string? stuid);
|
||||
|
||||
if (hasSToken && hasSTuid)
|
||||
if (TryGetValue(STOKEN, out string? stoken) && TryGetValue(STUID, out string? stuid))
|
||||
{
|
||||
cookie = new Cookie(new()
|
||||
{
|
||||
[STOKEN] = stoken!,
|
||||
[STUID] = stuid!,
|
||||
[STOKEN] = stoken,
|
||||
[STUID] = stuid,
|
||||
});
|
||||
|
||||
return true;
|
||||
|
||||
@@ -31,7 +31,8 @@ internal sealed class DynamicSecretHandler : DelegatingHandler
|
||||
return await base.SendAsync(request, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static async Task ProcessRequestWithOptionsAsync(HttpRequestMessage request, DynamicSecretCreationOptions options, CancellationToken token)
|
||||
[SuppressMessage("", "CA1308")]
|
||||
private static async ValueTask ProcessRequestWithOptionsAsync(HttpRequestMessage request, DynamicSecretCreationOptions options, CancellationToken token)
|
||||
{
|
||||
string salt = HoyolabOptions.Salts[options.SaltType];
|
||||
|
||||
@@ -44,11 +45,12 @@ internal sealed class DynamicSecretHandler : DelegatingHandler
|
||||
// ds2 b & q process
|
||||
if (options.Version == DynamicSecretVersion.Gen2)
|
||||
{
|
||||
string b = request.Content != null
|
||||
string b = request.Content is not null
|
||||
? await request.Content.ReadAsStringAsync(token).ConfigureAwait(false)
|
||||
: options.DefaultBody; // PROD's default value is {}
|
||||
|
||||
string[] queries = Uri.UnescapeDataString(request.RequestUri!.Query).Split('?', 2);
|
||||
ArgumentNullException.ThrowIfNull(request.RequestUri);
|
||||
string[] queries = Uri.UnescapeDataString(request.RequestUri.Query).Split('?', 2);
|
||||
string q = queries.Length == 2 ? string.Join('&', queries[1].Split('&').OrderBy(x => x)) : string.Empty;
|
||||
|
||||
dsContent = $"{dsContent}&b={b}&q={q}";
|
||||
|
||||
@@ -9,6 +9,6 @@ namespace Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
internal class UseDynamicSecretAttribute : Attribute
|
||||
internal sealed class UseDynamicSecretAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -32,20 +32,20 @@ internal sealed class Announcement : AnnouncementContent
|
||||
TimeSpan span = StartTime - now;
|
||||
if (span.TotalDays <= 1)
|
||||
{
|
||||
return string.Format(SH.WebAnnouncementTimeHoursBeginFormat, (int)span.TotalHours);
|
||||
return SH.WebAnnouncementTimeHoursBeginFormat.Format((int)span.TotalHours);
|
||||
}
|
||||
|
||||
return string.Format(SH.WebAnnouncementTimeDaysBeginFormat, (int)span.TotalDays);
|
||||
return SH.WebAnnouncementTimeDaysBeginFormat.Format((int)span.TotalDays);
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeSpan span = EndTime - now;
|
||||
if (span.TotalDays <= 1)
|
||||
{
|
||||
return string.Format(SH.WebAnnouncementTimeHoursEndFormat, (int)span.TotalHours);
|
||||
return SH.WebAnnouncementTimeHoursEndFormat.Format((int)span.TotalHours);
|
||||
}
|
||||
|
||||
return string.Format(SH.WebAnnouncementTimeDaysEndFormat, (int)span.TotalDays);
|
||||
return SH.WebAnnouncementTimeDaysEndFormat.Format((int)span.TotalDays);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ internal sealed partial class AnnouncementClient
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>公告列表</returns>
|
||||
public async Task<Response<AnnouncementWrapper>> GetAnnouncementsAsync(CancellationToken cancellationToken = default)
|
||||
public async ValueTask<Response<AnnouncementWrapper>> GetAnnouncementsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
Response<AnnouncementWrapper>? resp = await httpClient
|
||||
.TryCatchGetFromJsonAsync<Response<AnnouncementWrapper>>(ApiEndpoints.AnnList, jsonSerializerOptions, logger, cancellationToken)
|
||||
@@ -37,7 +37,7 @@ internal sealed partial class AnnouncementClient
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>公告内容列表</returns>
|
||||
public async Task<Response<ListWrapper<AnnouncementContent>>> GetAnnouncementContentsAsync(CancellationToken cancellationToken = default)
|
||||
public async ValueTask<Response<ListWrapper<AnnouncementContent>>> GetAnnouncementContentsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
Response<ListWrapper<AnnouncementContent>>? resp = await httpClient
|
||||
.TryCatchGetFromJsonAsync<Response<ListWrapper<AnnouncementContent>>>(ApiEndpoints.AnnContent, jsonSerializerOptions, logger, cancellationToken)
|
||||
|
||||
@@ -25,7 +25,7 @@ internal sealed partial class GachaInfoClient
|
||||
/// <param name="options">查询</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>单个祈愿记录页面</returns>
|
||||
public async Task<Response<GachaLogPage>> GetGachaLogPageAsync(GachaLogQueryOptions options, CancellationToken token = default)
|
||||
public async ValueTask<Response<GachaLogPage>> GetGachaLogPageAsync(GachaLogQueryOptions options, CancellationToken token = default)
|
||||
{
|
||||
string query = options.ToQueryString();
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ internal struct GachaLogQueryOptions
|
||||
/// 转换到查询字符串
|
||||
/// </summary>
|
||||
/// <returns>匹配的查询字符串</returns>
|
||||
public string ToQueryString()
|
||||
public readonly string ToQueryString()
|
||||
{
|
||||
// Make the cached end id into query.
|
||||
innerQuery.Set("end_id", EndId);
|
||||
|
||||
@@ -27,17 +27,17 @@ internal static class HoyolabHttpClientExtension
|
||||
|
||||
if (cookie.HasFlag(CookieType.CookieToken))
|
||||
{
|
||||
stringBuilder.Append(user.CookieToken).AppendIf(user.CookieToken != null, ';');
|
||||
stringBuilder.Append(user.CookieToken).AppendIf(user.CookieToken is not null, ';');
|
||||
}
|
||||
|
||||
if (cookie.HasFlag(CookieType.LToken))
|
||||
{
|
||||
stringBuilder.Append(user.LToken).AppendIf(user.LToken != null, ';');
|
||||
stringBuilder.Append(user.LToken).AppendIf(user.LToken is not null, ';');
|
||||
}
|
||||
|
||||
if (cookie.HasFlag(CookieType.SToken))
|
||||
{
|
||||
stringBuilder.Append(user.SToken).AppendIf(user.SToken != null, ';');
|
||||
stringBuilder.Append(user.SToken).AppendIf(user.SToken is not null, ';');
|
||||
}
|
||||
|
||||
string result = stringBuilder.ToString();
|
||||
|
||||
@@ -17,7 +17,7 @@ internal interface IPassportClient
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>cookie token</returns>
|
||||
Task<Response<UidCookieToken>> GetCookieAccountInfoBySTokenAsync(User user, CancellationToken token = default);
|
||||
ValueTask<Response<UidCookieToken>> GetCookieAccountInfoBySTokenAsync(User user, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取 LToken
|
||||
@@ -25,5 +25,5 @@ internal interface IPassportClient
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>uid 与 cookie token</returns>
|
||||
Task<Response<LTokenWrapper>> GetLTokenBySTokenAsync(User user, CancellationToken token = default);
|
||||
ValueTask<Response<LTokenWrapper>> GetLTokenBySTokenAsync(User user, CancellationToken token = default);
|
||||
}
|
||||
@@ -30,7 +30,7 @@ internal sealed partial class PassportClient : IPassportClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>cookie token</returns>
|
||||
[ApiInformation(Cookie = CookieType.SToken, Salt = SaltType.PROD)]
|
||||
public async Task<Response<UidCookieToken>> GetCookieAccountInfoBySTokenAsync(User user, CancellationToken token = default)
|
||||
public async ValueTask<Response<UidCookieToken>> GetCookieAccountInfoBySTokenAsync(User user, CancellationToken token = default)
|
||||
{
|
||||
Response<UidCookieToken>? resp = await httpClient
|
||||
.SetUser(user, CookieType.SToken)
|
||||
@@ -48,7 +48,7 @@ internal sealed partial class PassportClient : IPassportClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>uid 与 cookie token</returns>
|
||||
[ApiInformation(Cookie = CookieType.SToken, Salt = SaltType.PROD)]
|
||||
public async Task<Response<LTokenWrapper>> GetLTokenBySTokenAsync(User user, CancellationToken token = default)
|
||||
public async ValueTask<Response<LTokenWrapper>> GetLTokenBySTokenAsync(User user, CancellationToken token = default)
|
||||
{
|
||||
Response<LTokenWrapper>? resp = await httpClient
|
||||
.SetUser(user, CookieType.SToken)
|
||||
|
||||
@@ -31,7 +31,7 @@ internal sealed partial class PassportClient2
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>验证信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.LToken)]
|
||||
public async Task<Response<UserInfoWrapper>> VerifyLtokenAsync(User user, CancellationToken token)
|
||||
public async ValueTask<Response<UserInfoWrapper>> VerifyLtokenAsync(User user, CancellationToken token)
|
||||
{
|
||||
Response<UserInfoWrapper>? response = await httpClient
|
||||
.SetUser(user, CookieType.LToken)
|
||||
@@ -48,7 +48,7 @@ internal sealed partial class PassportClient2
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>登录数据</returns>
|
||||
[ApiInformation(Salt = SaltType.PROD)]
|
||||
public async Task<Response<LoginResult>> LoginBySTokenAsync(Cookie stokenV1, CancellationToken token = default)
|
||||
public async ValueTask<Response<LoginResult>> LoginBySTokenAsync(Cookie stokenV1, CancellationToken token = default)
|
||||
{
|
||||
HttpResponseMessage message = await httpClient
|
||||
.SetHeader("Cookie", stokenV1.ToString())
|
||||
|
||||
@@ -27,9 +27,12 @@ internal sealed partial class PassportClientOversea : IPassportClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>cookie token</returns>
|
||||
[ApiInformation(Cookie = CookieType.SToken)]
|
||||
public async Task<Response<UidCookieToken>> GetCookieAccountInfoBySTokenAsync(User user, CancellationToken token = default)
|
||||
public async ValueTask<Response<UidCookieToken>> GetCookieAccountInfoBySTokenAsync(User user, CancellationToken token = default)
|
||||
{
|
||||
STokenWrapper data = new(user.SToken?.GetValueOrDefault(Cookie.STOKEN)!, user.Aid!);
|
||||
string? stoken = user.SToken?.GetValueOrDefault(Cookie.STOKEN);
|
||||
ArgumentException.ThrowIfNullOrEmpty(stoken);
|
||||
ArgumentException.ThrowIfNullOrEmpty(user.Aid);
|
||||
STokenWrapper data = new(stoken, user.Aid);
|
||||
|
||||
Response<UidCookieToken>? resp = await httpClient
|
||||
.SetUser(user, CookieType.SToken)
|
||||
@@ -46,9 +49,12 @@ internal sealed partial class PassportClientOversea : IPassportClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>uid 与 cookie token</returns>
|
||||
[ApiInformation(Cookie = CookieType.SToken)]
|
||||
public async Task<Response<LTokenWrapper>> GetLTokenBySTokenAsync(User user, CancellationToken token = default)
|
||||
public async ValueTask<Response<LTokenWrapper>> GetLTokenBySTokenAsync(User user, CancellationToken token = default)
|
||||
{
|
||||
STokenWrapper data = new(user.SToken?.GetValueOrDefault(Cookie.STOKEN)!, user.Aid!);
|
||||
string? stoken = user.SToken?.GetValueOrDefault(Cookie.STOKEN);
|
||||
ArgumentException.ThrowIfNullOrEmpty(stoken);
|
||||
ArgumentException.ThrowIfNullOrEmpty(user.Aid);
|
||||
STokenWrapper data = new(stoken, user.Aid);
|
||||
|
||||
Response<LTokenWrapper>? resp = await httpClient
|
||||
.SetUser(user, CookieType.SToken)
|
||||
|
||||
@@ -26,7 +26,7 @@ internal sealed partial class ResourceClient
|
||||
/// <param name="scheme">方案</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>游戏资源</returns>
|
||||
public async Task<Response<GameResource>> GetResourceAsync(LaunchScheme scheme, CancellationToken token = default)
|
||||
public async ValueTask<Response<GameResource>> GetResourceAsync(LaunchScheme scheme, CancellationToken token = default)
|
||||
{
|
||||
string url = scheme.IsOversea
|
||||
? ApiOsEndpoints.SdkOsStaticLauncherResource(scheme)
|
||||
|
||||
@@ -31,9 +31,10 @@ internal sealed partial class AuthClient
|
||||
/// <param name="user">用户</param>
|
||||
/// <returns>操作凭证</returns>
|
||||
[ApiInformation(Cookie = CookieType.SToken, Salt = SaltType.K2)]
|
||||
public async Task<Response<ActionTicketWrapper>> GetActionTicketBySTokenAsync(string action, User user)
|
||||
public async ValueTask<Response<ActionTicketWrapper>> GetActionTicketBySTokenAsync(string action, User user)
|
||||
{
|
||||
string url = ApiEndpoints.AuthActionTicket(action, user.SToken?[Cookie.STOKEN] ?? string.Empty, user.Aid!);
|
||||
ArgumentException.ThrowIfNullOrEmpty(user.Aid);
|
||||
string url = ApiEndpoints.AuthActionTicket(action, user.SToken?[Cookie.STOKEN] ?? string.Empty, user.Aid);
|
||||
|
||||
Response<ActionTicketWrapper>? resp = await httpClient
|
||||
.SetUser(user, CookieType.SToken)
|
||||
@@ -51,7 +52,7 @@ internal sealed partial class AuthClient
|
||||
/// <param name="isOversea">是否为国际服</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>包含token的字典</returns>
|
||||
public async Task<Response<ListWrapper<NameToken>>> GetMultiTokenByLoginTicketAsync(Cookie cookie, bool isOversea, CancellationToken token = default)
|
||||
public async ValueTask<Response<ListWrapper<NameToken>>> GetMultiTokenByLoginTicketAsync(Cookie cookie, bool isOversea, CancellationToken token = default)
|
||||
{
|
||||
string loginTicket = cookie[Cookie.LOGIN_TICKET];
|
||||
string loginUid = cookie[Cookie.LOGIN_UID];
|
||||
|
||||
@@ -30,7 +30,7 @@ internal sealed partial class BindingClient
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>用户角色信息</returns>
|
||||
public async Task<Response<ListWrapper<UserGameRole>>> GetUserGameRolesOverseaAwareAsync(User user, CancellationToken token = default)
|
||||
public async ValueTask<Response<ListWrapper<UserGameRole>>> GetUserGameRolesOverseaAwareAsync(User user, CancellationToken token = default)
|
||||
{
|
||||
if (user.IsOversea)
|
||||
{
|
||||
@@ -63,7 +63,7 @@ internal sealed partial class BindingClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>用户角色信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.LToken)]
|
||||
public async Task<Response<ListWrapper<UserGameRole>>> GetUserGameRolesByActionTicketAsync(string actionTicket, User user, CancellationToken token = default)
|
||||
public async ValueTask<Response<ListWrapper<UserGameRole>>> GetUserGameRolesByActionTicketAsync(string actionTicket, User user, CancellationToken token = default)
|
||||
{
|
||||
string url = ApiEndpoints.UserGameRolesByActionTicket(actionTicket);
|
||||
|
||||
@@ -82,7 +82,7 @@ internal sealed partial class BindingClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>用户角色信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.LToken)]
|
||||
public async Task<Response<ListWrapper<UserGameRole>>> GetOverseaUserGameRolesByCookieAsync(User user, CancellationToken token = default)
|
||||
public async ValueTask<Response<ListWrapper<UserGameRole>>> GetOverseaUserGameRolesByCookieAsync(User user, CancellationToken token = default)
|
||||
{
|
||||
Response<ListWrapper<UserGameRole>>? resp = await httpClient
|
||||
.SetUser(user, CookieType.LToken)
|
||||
|
||||
@@ -30,7 +30,7 @@ internal sealed partial class BindingClient2
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>用户角色信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.SToken, Salt = SaltType.LK2)]
|
||||
public async Task<List<UserGameRole>> GetUserGameRolesBySTokenAsync(User user, CancellationToken token = default)
|
||||
public async ValueTask<List<UserGameRole>> GetUserGameRolesBySTokenAsync(User user, CancellationToken token = default)
|
||||
{
|
||||
Response<ListWrapper<UserGameRole>>? resp = await httpClient
|
||||
.SetUser(user, CookieType.SToken)
|
||||
@@ -50,7 +50,7 @@ internal sealed partial class BindingClient2
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>用户角色信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.SToken, Salt = SaltType.LK2)]
|
||||
public async Task<Response<GameAuthKey>> GenerateAuthenticationKeyAsync(User user, GenAuthKeyData data, CancellationToken token = default)
|
||||
public async ValueTask<Response<GameAuthKey>> GenerateAuthenticationKeyAsync(User user, GenAuthKeyData data, CancellationToken token = default)
|
||||
{
|
||||
Response<GameAuthKey>? resp = await httpClient
|
||||
.SetUser(user, CookieType.SToken)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Globalization;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||
|
||||
/// <summary>
|
||||
@@ -22,7 +24,7 @@ internal sealed class GenAuthKeyData
|
||||
{
|
||||
AuthAppId = authAppId;
|
||||
GameBiz = gameBiz;
|
||||
GameUid = int.Parse(uid.Value);
|
||||
GameUid = int.Parse(uid.Value, CultureInfo.InvariantCulture);
|
||||
Region = uid.Region;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ internal sealed partial class CalculateClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>消耗结果</returns>
|
||||
[ApiInformation(Cookie = CookieType.Cookie)]
|
||||
public async Task<Response<Consumption>> ComputeAsync(Model.Entity.User user, AvatarPromotionDelta delta, CancellationToken token = default)
|
||||
public async ValueTask<Response<Consumption>> ComputeAsync(Model.Entity.User user, AvatarPromotionDelta delta, CancellationToken token = default)
|
||||
{
|
||||
string referer = user.IsOversea
|
||||
? ApiOsEndpoints.ActHoyolabReferer
|
||||
@@ -54,7 +54,7 @@ internal sealed partial class CalculateClient
|
||||
/// <param name="userAndUid">用户与角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色列表</returns>
|
||||
public async Task<List<Avatar>> GetAvatarsAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
public async ValueTask<List<Avatar>> GetAvatarsAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
int currentPage = 1;
|
||||
SyncAvatarFilter filter = new() { Uid = userAndUid.Uid.Value, Region = userAndUid.Uid.Region };
|
||||
@@ -81,7 +81,7 @@ internal sealed partial class CalculateClient
|
||||
.TryCatchPostAsJsonAsync<SyncAvatarFilter, Response<ListWrapper<Avatar>>>(url, filter, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (resp != null && resp.IsOk())
|
||||
if (resp is not null && resp.IsOk())
|
||||
{
|
||||
avatars.AddRange(resp.Data.List);
|
||||
}
|
||||
@@ -93,7 +93,7 @@ internal sealed partial class CalculateClient
|
||||
|
||||
await Task.Delay(Random.Shared.Next(0, 1000), token).ConfigureAwait(false);
|
||||
}
|
||||
while (resp?.Data?.List?.Count == 20);
|
||||
while (resp.Data is { List.Count: 20 });
|
||||
|
||||
return avatars;
|
||||
}
|
||||
@@ -105,7 +105,7 @@ internal sealed partial class CalculateClient
|
||||
/// <param name="avatar">角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色详情</returns>
|
||||
public async Task<Response<AvatarDetail>> GetAvatarDetailAsync(UserAndUid userAndUid, Avatar avatar, CancellationToken token = default)
|
||||
public async ValueTask<Response<AvatarDetail>> GetAvatarDetailAsync(UserAndUid userAndUid, Avatar avatar, CancellationToken token = default)
|
||||
{
|
||||
string url = userAndUid.User.IsOversea
|
||||
? ApiOsEndpoints.CalculateSyncAvatarDetail(avatar.Id, userAndUid.Uid.Value)
|
||||
@@ -126,7 +126,7 @@ internal sealed partial class CalculateClient
|
||||
/// <param name="shareCode">摹本码</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>家具列表</returns>
|
||||
public async Task<Response<FurnitureListWrapper>> FurnitureBlueprintAsync(Model.Entity.User user, string shareCode, CancellationToken token)
|
||||
public async ValueTask<Response<FurnitureListWrapper>> FurnitureBlueprintAsync(Model.Entity.User user, string shareCode, CancellationToken token)
|
||||
{
|
||||
Response<FurnitureListWrapper>? resp = await httpClient
|
||||
.SetUser(user, CookieType.CookieToken)
|
||||
@@ -143,7 +143,7 @@ internal sealed partial class CalculateClient
|
||||
/// <param name="items">物品</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>消耗</returns>
|
||||
public async Task<Response<ListWrapper<Item>>> FurnitureComputeAsync(Model.Entity.User user, List<Item> items, CancellationToken token)
|
||||
public async ValueTask<Response<ListWrapper<Item>>> FurnitureComputeAsync(Model.Entity.User user, List<Item> items, CancellationToken token)
|
||||
{
|
||||
ListWrapper<IdCount> data = new() { List = items.Select(i => new IdCount { Id = i.Id, Count = i.Num }).ToList() };
|
||||
|
||||
|
||||
@@ -22,16 +22,19 @@ internal static class ItemHelper
|
||||
return new(0);
|
||||
}
|
||||
|
||||
if (right.IsNullOrEmpty())
|
||||
if (left.IsNullOrEmpty() && !right.IsNullOrEmpty())
|
||||
{
|
||||
return left!;
|
||||
return right;
|
||||
}
|
||||
|
||||
if (left.IsNullOrEmpty())
|
||||
if (right.IsNullOrEmpty() && !left.IsNullOrEmpty())
|
||||
{
|
||||
return right!;
|
||||
return left;
|
||||
}
|
||||
|
||||
ArgumentNullException.ThrowIfNull(left);
|
||||
ArgumentNullException.ThrowIfNull(right);
|
||||
|
||||
List<Item> result = new(left.Count + right.Count);
|
||||
result.AddRange(left);
|
||||
|
||||
|
||||
@@ -15,33 +15,21 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[UseDynamicSecret]
|
||||
[ConstructorGenerated(ResolveHttpClient = true)]
|
||||
[HttpClient(HttpClientConfiguration.XRpc)]
|
||||
internal sealed class CardClient
|
||||
internal sealed partial class CardClient
|
||||
{
|
||||
private readonly HttpClient httpClient;
|
||||
private readonly JsonSerializerOptions options;
|
||||
private readonly ILogger<CardClient> logger;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的卡片客户端
|
||||
/// </summary>
|
||||
/// <param name="httpClient">http客户端</param>
|
||||
/// <param name="options">选项</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
public CardClient(HttpClient httpClient, JsonSerializerOptions options, ILogger<CardClient> logger)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.options = options;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册验证码
|
||||
/// </summary>
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>注册结果</returns>
|
||||
public async Task<Response<VerificationRegistration>> CreateVerificationAsync(User user, CancellationToken token)
|
||||
public async ValueTask<Response<VerificationRegistration>> CreateVerificationAsync(User user, CancellationToken token)
|
||||
{
|
||||
Response<VerificationRegistration>? resp = await httpClient
|
||||
.SetUser(user, CookieType.LToken)
|
||||
@@ -59,7 +47,7 @@ internal sealed class CardClient
|
||||
/// <param name="validate">验证</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>验证结果</returns>
|
||||
public async Task<Response<VerificationResult>> VerifyVerificationAsync(string challenge, string validate, CancellationToken token)
|
||||
public async ValueTask<Response<VerificationResult>> VerifyVerificationAsync(string challenge, string validate, CancellationToken token)
|
||||
{
|
||||
VerificationData data = new(challenge, validate);
|
||||
|
||||
@@ -77,7 +65,7 @@ internal sealed class CardClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>桌面小组件数据</returns>
|
||||
[ApiInformation(Cookie = CookieType.SToken, Salt = SaltType.X6)]
|
||||
public async Task<Response<DailyNote.WidgetDailyNote>> GetWidgetDataAsync(User user, CancellationToken token)
|
||||
public async ValueTask<Response<DailyNote.WidgetDailyNote>> GetWidgetDataAsync(User user, CancellationToken token)
|
||||
{
|
||||
Response<DailyNote.WidgetDailyNote>? resp = await httpClient
|
||||
.SetUser(user, CookieType.SToken)
|
||||
|
||||
@@ -33,7 +33,7 @@ internal sealed class CardVerifier
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>流水号</returns>
|
||||
public async Task<string?> TryGetXrpcChallengeAsync(User user, CancellationToken token)
|
||||
public async ValueTask<string?> TryGetXrpcChallengeAsync(User user, CancellationToken token)
|
||||
{
|
||||
Response.Response<VerificationRegistration> registrationResponse = await cardClient.CreateVerificationAsync(user, token).ConfigureAwait(false);
|
||||
if (registrationResponse.IsOk())
|
||||
@@ -43,14 +43,14 @@ internal sealed class CardVerifier
|
||||
await geetestClient.GetTypeAsync(registration.Gt).ConfigureAwait(false);
|
||||
GeetestResult<GeetestData>? ajax = await geetestClient.GetAjaxAsync(registration).ConfigureAwait(false);
|
||||
|
||||
if (ajax?.Data.Validate is string validate)
|
||||
if (ajax?.Data.Validate is { } validate)
|
||||
{
|
||||
Response.Response<VerificationResult> verifyResponse = await cardClient.VerifyVerificationAsync(registration.Challenge, validate, token).ConfigureAwait(false);
|
||||
if (verifyResponse.IsOk())
|
||||
{
|
||||
VerificationResult result = verifyResponse.Data;
|
||||
|
||||
if (result.Challenge != null)
|
||||
if (result.Challenge is not null)
|
||||
{
|
||||
return result.Challenge;
|
||||
}
|
||||
@@ -58,6 +58,6 @@ internal sealed class CardVerifier
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -38,10 +38,10 @@ internal sealed class DailyNote : DailyNoteCommon
|
||||
0 => SH.WebDailyNoteRecoveryTimeDay0,
|
||||
1 => SH.WebDailyNoteRecoveryTimeDay1,
|
||||
2 => SH.WebDailyNoteRecoveryTimeDay2,
|
||||
_ => string.Format(SH.WebDailyNoteRecoveryTimeDayFormat, totalDays),
|
||||
_ => SH.WebDailyNoteRecoveryTimeDayFormat.Format(totalDays),
|
||||
};
|
||||
|
||||
return string.Format(SH.WebDailyNoteResinRecoveryFormat, day, reach);
|
||||
return SH.WebDailyNoteResinRecoveryFormat.Format(day, reach);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,9 +129,9 @@ internal sealed class DailyNote : DailyNoteCommon
|
||||
0 => SH.WebDailyNoteRecoveryTimeDay0,
|
||||
1 => SH.WebDailyNoteRecoveryTimeDay1,
|
||||
2 => SH.WebDailyNoteRecoveryTimeDay2,
|
||||
_ => string.Format(SH.WebDailyNoteRecoveryTimeDayFormat, totalDays),
|
||||
_ => SH.WebDailyNoteRecoveryTimeDayFormat.Format(totalDays),
|
||||
};
|
||||
return string.Format(SH.WebDailyNoteHomeCoinRecoveryFormat, day, reach);
|
||||
return SH.WebDailyNoteHomeCoinRecoveryFormat.Format(day, reach);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,8 +84,8 @@ internal sealed class Expedition
|
||||
|
||||
TimeSpan ts = new(0, 0, RemainedTime);
|
||||
return ts.Hours > 0
|
||||
? string.Format(SH.WebDailyNoteExpeditionRemainHoursFormat, ts.Hours)
|
||||
: string.Format(SH.WebDailyNoteExpeditionRemainMinutesFormat, ts.Minutes);
|
||||
? SH.WebDailyNoteExpeditionRemainHoursFormat.Format(ts.Hours)
|
||||
: SH.WebDailyNoteExpeditionRemainMinutesFormat.Format(ts.Minutes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,10 +67,10 @@ internal sealed class RecoveryTime
|
||||
else
|
||||
{
|
||||
return new StringBuilder()
|
||||
.AppendIf(Day > 0, string.Format(SH.WebDailyNoteTransformerDaysFormat, Day))
|
||||
.AppendIf(Hour > 0, string.Format(SH.WebDailyNoteTransformerHoursFormat, Hour))
|
||||
.AppendIf(Minute > 0, string.Format(SH.WebDailyNoteTransformerMinutesFormat, Minute))
|
||||
.AppendIf(Second > 0, string.Format(SH.WebDailyNoteTransformerSecondsFormat, Second))
|
||||
.AppendIf(Day > 0, SH.WebDailyNoteTransformerDaysFormat.Format(Day))
|
||||
.AppendIf(Hour > 0, SH.WebDailyNoteTransformerHoursFormat.Format(Hour))
|
||||
.AppendIf(Minute > 0, SH.WebDailyNoteTransformerMinutesFormat.Format(Minute))
|
||||
.AppendIf(Second > 0, SH.WebDailyNoteTransformerSecondsFormat.Format(Second))
|
||||
.Append(SH.WebDailyNoteTransformerAppend)
|
||||
.ToString();
|
||||
}
|
||||
@@ -92,10 +92,10 @@ internal sealed class RecoveryTime
|
||||
else
|
||||
{
|
||||
return new StringBuilder()
|
||||
.AppendIf(Day > 0, string.Format(SH.WebDailyNoteTransformerDaysFormat, Day))
|
||||
.AppendIf(Hour > 0, string.Format(SH.WebDailyNoteTransformerHoursFormat, Hour))
|
||||
.AppendIf(Minute > 0, string.Format(SH.WebDailyNoteTransformerMinutesFormat, Minute))
|
||||
.AppendIf(Second > 0, string.Format(SH.WebDailyNoteTransformerSecondsFormat, Second))
|
||||
.AppendIf(Day > 0, SH.WebDailyNoteTransformerDaysFormat.Format(Day))
|
||||
.AppendIf(Hour > 0, SH.WebDailyNoteTransformerHoursFormat.Format(Hour))
|
||||
.AppendIf(Minute > 0, SH.WebDailyNoteTransformerMinutesFormat.Format(Minute))
|
||||
.AppendIf(Second > 0, SH.WebDailyNoteTransformerSecondsFormat.Format(Second))
|
||||
.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>实时便笺</returns>
|
||||
[ApiInformation(Cookie = CookieType.Cookie, Salt = SaltType.X4)]
|
||||
public async Task<Response<DailyNote.DailyNote>> GetDailyNoteAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
public async ValueTask<Response<DailyNote.DailyNote>> GetDailyNoteAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
Response<DailyNote.DailyNote>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.Cookie)
|
||||
@@ -48,7 +48,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
resp.Message = SH.WebDailyNoteVerificationFailed;
|
||||
CardVerifier cardVerifier = serviceProvider.GetRequiredService<CardVerifier>();
|
||||
|
||||
if (await cardVerifier.TryGetXrpcChallengeAsync(userAndUid.User, token).ConfigureAwait(false) is string challenge)
|
||||
if (await cardVerifier.TryGetXrpcChallengeAsync(userAndUid.User, token).ConfigureAwait(false) is { } challenge)
|
||||
{
|
||||
resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.Cookie)
|
||||
@@ -69,7 +69,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>玩家的基础信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.LToken, Salt = SaltType.X4)]
|
||||
public async Task<Response<PlayerInfo>> GetPlayerInfoAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
public async ValueTask<Response<PlayerInfo>> GetPlayerInfoAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
Response<PlayerInfo>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.LToken)
|
||||
@@ -88,7 +88,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>深渊信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.Cookie, Salt = SaltType.X4)]
|
||||
public async Task<Response<SpiralAbyss.SpiralAbyss>> GetSpiralAbyssAsync(UserAndUid userAndUid, SpiralAbyssSchedule schedule, CancellationToken token = default)
|
||||
public async ValueTask<Response<SpiralAbyss.SpiralAbyss>> GetSpiralAbyssAsync(UserAndUid userAndUid, SpiralAbyssSchedule schedule, CancellationToken token = default)
|
||||
{
|
||||
Response<SpiralAbyss.SpiralAbyss>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.Cookie)
|
||||
@@ -106,7 +106,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色基本信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.LToken, Salt = SaltType.X4)]
|
||||
public async Task<Response<BasicRoleInfo>> GetRoleBasicInfoAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
public async ValueTask<Response<BasicRoleInfo>> GetRoleBasicInfoAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
Response<BasicRoleInfo>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.LToken)
|
||||
@@ -125,7 +125,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色列表</returns>
|
||||
[ApiInformation(Cookie = CookieType.LToken, Salt = SaltType.X4)]
|
||||
public async Task<Response<CharacterWrapper>> GetCharactersAsync(UserAndUid userAndUid, PlayerInfo playerInfo, CancellationToken token = default)
|
||||
public async ValueTask<Response<CharacterWrapper>> GetCharactersAsync(UserAndUid userAndUid, PlayerInfo playerInfo, CancellationToken token = default)
|
||||
{
|
||||
CharacterData data = new(userAndUid.Uid, playerInfo.Avatars.Select(x => x.Id));
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ internal sealed partial class GameRecordClientOversea : IGameRecordClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>实时便笺</returns>
|
||||
[ApiInformation(Cookie = CookieType.Cookie, Salt = SaltType.OSX4)]
|
||||
public async Task<Response<DailyNote.DailyNote>> GetDailyNoteAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
public async ValueTask<Response<DailyNote.DailyNote>> GetDailyNoteAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
Response<DailyNote.DailyNote>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.Cookie)
|
||||
@@ -49,7 +49,7 @@ internal sealed partial class GameRecordClientOversea : IGameRecordClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>玩家的基础信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.LToken, Salt = SaltType.OSX4)]
|
||||
public async Task<Response<PlayerInfo>> GetPlayerInfoAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
public async ValueTask<Response<PlayerInfo>> GetPlayerInfoAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
Response<PlayerInfo>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.Cookie)
|
||||
@@ -68,7 +68,7 @@ internal sealed partial class GameRecordClientOversea : IGameRecordClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>深渊信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.Cookie, Salt = SaltType.OSX4)]
|
||||
public async Task<Response<SpiralAbyss.SpiralAbyss>> GetSpiralAbyssAsync(UserAndUid userAndUid, SpiralAbyssSchedule schedule, CancellationToken token = default)
|
||||
public async ValueTask<Response<SpiralAbyss.SpiralAbyss>> GetSpiralAbyssAsync(UserAndUid userAndUid, SpiralAbyssSchedule schedule, CancellationToken token = default)
|
||||
{
|
||||
Response<SpiralAbyss.SpiralAbyss>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.Cookie)
|
||||
@@ -87,7 +87,7 @@ internal sealed partial class GameRecordClientOversea : IGameRecordClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色列表</returns>
|
||||
[ApiInformation(Cookie = CookieType.LToken, Salt = SaltType.OSX4)]
|
||||
public async Task<Response<CharacterWrapper>> GetCharactersAsync(UserAndUid userAndUid, PlayerInfo playerInfo, CancellationToken token = default)
|
||||
public async ValueTask<Response<CharacterWrapper>> GetCharactersAsync(UserAndUid userAndUid, PlayerInfo playerInfo, CancellationToken token = default)
|
||||
{
|
||||
CharacterData data = new(userAndUid.Uid, playerInfo.Avatars.Select(x => x.Id));
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ internal interface IGameRecordClient
|
||||
/// <param name="playerInfo">玩家的基础信息</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色列表</returns>
|
||||
Task<Response<CharacterWrapper>> GetCharactersAsync(UserAndUid userAndUid, PlayerInfo playerInfo, CancellationToken token = default);
|
||||
ValueTask<Response<CharacterWrapper>> GetCharactersAsync(UserAndUid userAndUid, PlayerInfo playerInfo, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取实时便笺
|
||||
@@ -28,7 +28,7 @@ internal interface IGameRecordClient
|
||||
/// <param name="userAndUid">用户与角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>实时便笺</returns>
|
||||
Task<Response<DailyNote.DailyNote>> GetDailyNoteAsync(UserAndUid userAndUid, CancellationToken token = default);
|
||||
ValueTask<Response<DailyNote.DailyNote>> GetDailyNoteAsync(UserAndUid userAndUid, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 获取玩家基础信息
|
||||
@@ -36,7 +36,7 @@ internal interface IGameRecordClient
|
||||
/// <param name="userAndUid">用户与角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>玩家的基础信息</returns>
|
||||
Task<Response<PlayerInfo>> GetPlayerInfoAsync(UserAndUid userAndUid, CancellationToken token = default);
|
||||
ValueTask<Response<PlayerInfo>> GetPlayerInfoAsync(UserAndUid userAndUid, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 获取玩家深渊信息
|
||||
@@ -45,5 +45,5 @@ internal interface IGameRecordClient
|
||||
/// <param name="schedule">1:当期,2:上期</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>深渊信息</returns>
|
||||
Task<Response<SpiralAbyss.SpiralAbyss>> GetSpiralAbyssAsync(UserAndUid userAndUid, SpiralAbyssSchedule schedule, CancellationToken token = default);
|
||||
ValueTask<Response<SpiralAbyss.SpiralAbyss>> GetSpiralAbyssAsync(UserAndUid userAndUid, SpiralAbyssSchedule schedule, CancellationToken token = default);
|
||||
}
|
||||
@@ -17,7 +17,7 @@ internal static class HttpClientExtension
|
||||
private const string RequestErrorMessage = "请求异常已忽略";
|
||||
|
||||
/// <inheritdoc cref="HttpClientJsonExtensions.GetFromJsonAsync{TValue}(HttpClient, string?, JsonSerializerOptions?, CancellationToken)"/>
|
||||
internal static async Task<T?> TryCatchGetFromJsonAsync<T>(this HttpClient httpClient, string requestUri, JsonSerializerOptions options, ILogger logger, CancellationToken token = default)
|
||||
internal static async ValueTask<T?> TryCatchGetFromJsonAsync<T>(this HttpClient httpClient, string requestUri, JsonSerializerOptions options, ILogger logger, CancellationToken token = default)
|
||||
where T : class
|
||||
{
|
||||
try
|
||||
@@ -47,7 +47,7 @@ internal static class HttpClientExtension
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="HttpClientJsonExtensions.PostAsJsonAsync{TValue}(HttpClient, string?, TValue, JsonSerializerOptions?, CancellationToken)"/>
|
||||
internal static async Task<TResult?> TryCatchPostAsJsonAsync<TValue, TResult>(this HttpClient httpClient, string requestUri, TValue value, JsonSerializerOptions options, ILogger logger, CancellationToken token = default)
|
||||
internal static async ValueTask<TResult?> TryCatchPostAsJsonAsync<TValue, TResult>(this HttpClient httpClient, string requestUri, TValue value, JsonSerializerOptions options, ILogger logger, CancellationToken token = default)
|
||||
where TResult : class
|
||||
{
|
||||
try
|
||||
@@ -78,7 +78,7 @@ internal static class HttpClientExtension
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="HttpClientJsonExtensions.PostAsJsonAsync{TValue}(HttpClient, string?, TValue, JsonSerializerOptions?, CancellationToken)"/>
|
||||
internal static async Task<TResult?> TryCatchPostAsJsonAsync<TValue, TResult>(this HttpClient httpClient, string requestUri, TValue value, CancellationToken token = default)
|
||||
internal static async ValueTask<TResult?> TryCatchPostAsJsonAsync<TValue, TResult>(this HttpClient httpClient, string requestUri, TValue value, CancellationToken token = default)
|
||||
where TResult : class
|
||||
{
|
||||
try
|
||||
@@ -103,4 +103,4 @@ internal static class HttpClientExtension
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ internal sealed class HomaGachaLogClient
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>祈愿统计信息</returns>
|
||||
public async Task<Response<GachaEventStatistics>> GetGachaEventStatisticsAsync(CancellationToken token = default)
|
||||
public async ValueTask<Response<GachaEventStatistics>> GetGachaEventStatisticsAsync(CancellationToken token = default)
|
||||
{
|
||||
Response<GachaEventStatistics>? resp = await httpClient
|
||||
.TryCatchGetFromJsonAsync<Response<GachaEventStatistics>>(HutaoEndpoints.GachaLogStatisticsCurrentEvents, options, logger, token)
|
||||
@@ -70,7 +70,7 @@ internal sealed class HomaGachaLogClient
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>Uid 列表</returns>
|
||||
[Obsolete("Use GetGachaEntriesAsync instead")]
|
||||
public async Task<Response<List<string>>> GetUidsAsync(CancellationToken token = default)
|
||||
public async ValueTask<Response<List<string>>> GetUidsAsync(CancellationToken token = default)
|
||||
{
|
||||
Response<List<string>>? resp = await httpClient
|
||||
.TryCatchGetFromJsonAsync<Response<List<string>>>(HutaoEndpoints.GachaLogUids, options, logger, token)
|
||||
@@ -99,7 +99,7 @@ internal sealed class HomaGachaLogClient
|
||||
/// <param name="uid">uid</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>末尾Id</returns>
|
||||
public async Task<Response<EndIds>> GetEndIdsAsync(string uid, CancellationToken token = default)
|
||||
public async ValueTask<Response<EndIds>> GetEndIdsAsync(string uid, CancellationToken token = default)
|
||||
{
|
||||
Response<EndIds>? resp = await httpClient
|
||||
.TryCatchGetFromJsonAsync<Response<EndIds>>(HutaoEndpoints.GachaLogEndIds(uid), options, logger, token)
|
||||
@@ -115,7 +115,7 @@ internal sealed class HomaGachaLogClient
|
||||
/// <param name="endIds">末尾 Id</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>云端祈愿记录</returns>
|
||||
public async Task<Response<List<GachaItem>>> RetrieveGachaItemsAsync(string uid, EndIds endIds, CancellationToken token = default)
|
||||
public async ValueTask<Response<List<GachaItem>>> RetrieveGachaItemsAsync(string uid, EndIds endIds, CancellationToken token = default)
|
||||
{
|
||||
UidAndEndIds uidAndEndIds = new(uid, endIds);
|
||||
|
||||
@@ -133,7 +133,7 @@ internal sealed class HomaGachaLogClient
|
||||
/// <param name="gachaItems">祈愿记录</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应</returns>
|
||||
public async Task<Response.Response> UploadGachaItemsAsync(string uid, List<GachaItem> gachaItems, CancellationToken token = default)
|
||||
public async ValueTask<Response.Response> UploadGachaItemsAsync(string uid, List<GachaItem> gachaItems, CancellationToken token = default)
|
||||
{
|
||||
UidAndItems uidAndItems = new(uid, gachaItems);
|
||||
|
||||
@@ -150,7 +150,7 @@ internal sealed class HomaGachaLogClient
|
||||
/// <param name="uid">uid</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应</returns>
|
||||
public async Task<Response.Response> DeleteGachaItemsAsync(string uid, CancellationToken token = default)
|
||||
public async ValueTask<Response.Response> DeleteGachaItemsAsync(string uid, CancellationToken token = default)
|
||||
{
|
||||
Response.Response? resp = await httpClient
|
||||
.TryCatchGetFromJsonAsync<Response<List<GachaItem>>>(HutaoEndpoints.GachaLogDelete(uid), options, logger, token)
|
||||
|
||||
@@ -33,7 +33,7 @@ internal sealed class HomaLogUploadClient
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
/// <param name="exception">异常</param>
|
||||
/// <returns>任务</returns>
|
||||
public async Task<string?> UploadLogAsync(IServiceProvider serviceProvider, Exception exception)
|
||||
public async ValueTask<string?> UploadLogAsync(IServiceProvider serviceProvider, Exception exception)
|
||||
{
|
||||
HutaoLog log = BuildFromException(serviceProvider, exception);
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ internal sealed partial class HomaPassportClient
|
||||
/// <param name="isResetPassword">是否重置账号密码</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应</returns>
|
||||
public async Task<Response.Response> VerifyAsync(string email, bool isResetPassword, CancellationToken token = default)
|
||||
public async ValueTask<Response.Response> VerifyAsync(string email, bool isResetPassword, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, object> data = new()
|
||||
{
|
||||
@@ -67,7 +67,7 @@ internal sealed partial class HomaPassportClient
|
||||
/// <param name="verifyCode">验证码</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应,包含登录令牌</returns>
|
||||
public async Task<Response<string>> RegisterAsync(string email, string password, string verifyCode, CancellationToken token = default)
|
||||
public async ValueTask<Response<string>> RegisterAsync(string email, string password, string verifyCode, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, string> data = new()
|
||||
{
|
||||
@@ -91,7 +91,7 @@ internal sealed partial class HomaPassportClient
|
||||
/// <param name="verifyCode">验证码</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应,包含登录令牌</returns>
|
||||
public async Task<Response<string>> ResetPasswordAsync(string email, string password, string verifyCode, CancellationToken token = default)
|
||||
public async ValueTask<Response<string>> ResetPasswordAsync(string email, string password, string verifyCode, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, string> data = new()
|
||||
{
|
||||
@@ -114,7 +114,7 @@ internal sealed partial class HomaPassportClient
|
||||
/// <param name="password">密码</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应,包含登录令牌</returns>
|
||||
public async Task<Response<string>> LoginAsync(string email, string password, CancellationToken token = default)
|
||||
public async ValueTask<Response<string>> LoginAsync(string email, string password, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, string> data = new()
|
||||
{
|
||||
@@ -135,7 +135,7 @@ internal sealed partial class HomaPassportClient
|
||||
/// <param name="authToken">验证令牌</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>用户信息</returns>
|
||||
public async Task<Response<UserInfo>> GetUserInfoAsync(string authToken, CancellationToken token = default)
|
||||
public async ValueTask<Response<UserInfo>> GetUserInfoAsync(string authToken, CancellationToken token = default)
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Authorization = new("Bearer", authToken);
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ internal readonly struct QueryString
|
||||
return new QueryString();
|
||||
}
|
||||
|
||||
int questionMarkIndex = queryString.IndexOf('?');
|
||||
int questionMarkIndex = queryString.AsSpan().IndexOf('?');
|
||||
queryString = queryString[(questionMarkIndex + 1)..];
|
||||
|
||||
string[] pairs = queryString.Split('&', ';');
|
||||
|
||||
Reference in New Issue
Block a user