support Action Ticket for #207

This commit is contained in:
DismissedLight
2022-11-13 19:01:57 +08:00
parent 58b34ea60a
commit 971f319b76
10 changed files with 198 additions and 13 deletions

View File

@@ -137,7 +137,7 @@ public class User : ObservableObject
.ConfigureAwait(false);
UserGameRoles = await userGameRoleClient
.GetUserGameRolesAsync(this, token)
.GetUserGameRolesAsync(Entity, token)
.ConfigureAwait(false);
SelectedUserGameRole = UserGameRoles.FirstOrFirstOrDefault(role => role.IsChosen);

View File

@@ -2,11 +2,6 @@
// Licensed under the MIT license.
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Snap.Hutao.Web.Hoyolab.Annotation;
@@ -15,7 +10,7 @@ namespace Snap.Hutao.Web.Hoyolab.Annotation;
/// </summary>
/// <typeparam name="TReturnType">API 的返回类型</typeparam>
[AttributeUsage(AttributeTargets.Method)]
internal class ApiInformationAttribute<TReturnType> : Attribute
internal class ApiInformationAttribute : Attribute
{
/// <summary>
/// Cookie类型

View File

@@ -1,6 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using System.ComponentModel.DataAnnotations;
namespace Snap.Hutao.Web.Hoyolab;
/// <summary>
@@ -105,7 +107,17 @@ internal static class ApiEndpoints
/// <summary>
/// 用户游戏角色
/// </summary>
public const string UserGameRoles = $"{ApiTaKumiBindingApi}/getUserGameRolesByCookie?game_biz=hk4e_cn";
/// <param name="actionTicket">操作凭证</param>
/// <returns>用户游戏角色字符串</returns>
public static string UserGameRolesByActionTicket(string actionTicket)
{
return $"{ApiTaKumiBindingApi}/getUserGameRolesByCookie?action_ticket={actionTicket}&game_biz=hk4e_cn";
}
/// <summary>
/// 用户游戏角色
/// </summary>
public const string UserGameRolesByCookie = $"{ApiTaKumiBindingApi}/getUserGameRolesByCookie?game_biz=hk4e_cn";
/// <summary>
/// AuthKey
@@ -115,6 +127,18 @@ internal static class ApiEndpoints
#region Auth
/// <summary>
/// 获取 stoken 与 ltoken
/// </summary>
/// <param name="actionType">操作类型 game_role</param>
/// <param name="stoken">Stoken</param>
/// <param name="uid">uid</param>
/// <returns>Url</returns>
public static string AuthActionTicket(string actionType, string stoken, string uid)
{
return $"{ApiTakumiAuthApi}/getMultiTokenByLoginTicket?action_type={actionType}&stoken={Uri.EscapeDataString(stoken)}&uid={uid}";
}
/// <summary>
/// 获取 stoken 与 ltoken
/// </summary>

View File

@@ -39,7 +39,7 @@ internal class CardClient
/// <param name="user">用户</param>
/// <param name="token">取消令牌</param>
/// <returns>桌面小组件数据</returns>
[ApiInformation<WidgetData>(Cookie = CookieType.Stoken, Salt = SaltType.X6)]
[ApiInformation(Cookie = CookieType.Stoken, Salt = SaltType.X6)]
public async Task<WidgetData?> GetWidgetDataAsync(User user, CancellationToken token)
{
Response<DataWrapper<WidgetData>>? resp = await httpClient

View File

@@ -13,6 +13,11 @@ public enum CookieType
/// </summary>
None,
/// <summary>
/// 需要 Ltoken 与 e_hk4e_token
/// </summary>
Ltoken,
/// <summary>
/// 需要 Stoken
/// </summary>

View File

@@ -38,7 +38,7 @@ internal class PassportClient
/// <param name="user">用户</param>
/// <param name="token">取消令牌</param>
/// <returns>验证信息</returns>
[ApiInformation<VerifyInformation>(Cookie = CookieType.All)]
[ApiInformation(Cookie = CookieType.All)]
public async Task<VerifyInformation?> VerifyLtokenAsync(User user, CancellationToken token)
{
Response<VerifyInformation>? response = await httpClient

View File

@@ -0,0 +1,92 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
using Snap.Hutao.Web.Response;
using System.Net.Http;
namespace Snap.Hutao.Web.Hoyolab.Takumi.Auth;
/// <summary>
/// 账户信息
/// </summary>
[SuppressMessage("", "SA1600")]
public class AccountInfo
{
[JsonPropertyName("is_realname")]
public bool IsRealname { get; set; }
[JsonPropertyName("mobile")]
public string Mobile { get; set; } = default!;
[JsonPropertyName("safe_mobile")]
public string SafeMobile { get; set; } = default!;
[JsonPropertyName("account_id")]
public string AccountId { get; set; } = default!;
[JsonPropertyName("account_name")]
public string AccountName { get; set; } = default!;
[JsonPropertyName("email")]
public string Email { get; set; } = default!;
[JsonPropertyName("is_email_verify")]
public bool IsEmailVerify { get; set; }
[JsonPropertyName("area_code")]
public string AreaCode { get; set; } = default!;
[JsonPropertyName("safe_area_code")]
public string SafeAreaCode { get; set; } = default!;
[JsonPropertyName("real_name")]
public string RealName { get; set; } = default!;
[JsonPropertyName("identity_code")]
public string IdentityCode { get; set; } = default!;
[JsonPropertyName("create_time")]
public string CreateTime { get; set; } = default!;
[JsonPropertyName("create_ip")]
public string CreateIp { get; set; } = default!;
[JsonPropertyName("change_pwd_time")]
public string ChangePwdTime { get; set; } = default!;
[JsonPropertyName("nickname")]
public string Nickname { get; set; } = default!;
[JsonPropertyName("user_icon_id")]
public int UserIconId { get; set; }
[JsonPropertyName("safe_level")]
public int SafeLevel { get; set; }
[JsonPropertyName("black_endtime")]
public string BlackEndtime { get; set; } = default!;
[JsonPropertyName("black_note")]
public string BlackNote { get; set; } = default!;
[JsonPropertyName("gender")]
public int Gender { get; set; }
[JsonPropertyName("real_stat")]
public int RealStat { get; set; }
[JsonPropertyName("apple_name")]
public string AppleName { get; set; } = default!;
[JsonPropertyName("sony_name")]
public string SonyName { get; set; } = default!;
[JsonPropertyName("tap_name")]
public string TapName { get; set; } = default!;
[JsonPropertyName("reactivate_ticket")]
public string ReactivateTicket { get; set; } = default!;
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
using Snap.Hutao.Web.Response;
using System.Net.Http;
namespace Snap.Hutao.Web.Hoyolab.Takumi.Auth;
/// <summary>
/// 操作凭证包装器
/// </summary>
public class ActionTicketWrapper
{
/// <summary>
/// 凭证
/// </summary>
[JsonPropertyName("ticket")]
public string Ticket { get; set; }
/// <summary>
/// 是否验证
/// </summary>
[JsonPropertyName("is_verified")]
public bool IsVerified { get; set; }
/// <summary>
/// 账户信息
/// </summary>
[JsonPropertyName("account_info")]
public AccountInfo AccountInfo { get; set; }
}

View File

@@ -2,6 +2,8 @@
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Web.Hoyolab.Annotation;
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
using Snap.Hutao.Web.Response;
using System.Net.Http;
@@ -31,6 +33,30 @@ internal class AuthClient
this.logger = logger;
}
/// <summary>
/// 异步获取操作凭证
/// </summary>
/// <param name="action">操作</param>
/// <param name="user">用户</param>
/// <returns>操作凭证</returns>
[ApiInformation(Cookie = CookieType.Stoken, Salt = DynamicSecret.SaltType.K2)]
public async Task<string?> GetActionTicketByStokenAsync(string action, User user)
{
if (user.Cookie!.TryGetValue(Cookie.STOKEN, out string? stoken))
{
if (user.Cookie.TryGetUid(out string? uid))
{
Response<ActionTicketWrapper>? resp = await httpClient
.TryCatchGetFromJsonAsync<Response<ActionTicketWrapper>>(ApiEndpoints.AuthActionTicket(action, stoken, uid), options, logger)
.ConfigureAwait(false);
return resp.Data?.Ticket;
}
}
return null;
}
/// <summary>
/// 获取 MultiToken
/// </summary>

View File

@@ -4,6 +4,7 @@
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Extension;
using Snap.Hutao.Model.Binding.User;
using Snap.Hutao.Web.Hoyolab.Annotation;
using Snap.Hutao.Web.Response;
using System.Net.Http;
@@ -35,12 +36,21 @@ internal class BindingClient
/// <summary>
/// 获取用户角色信息
/// </summary>
/// <param name="actionTicket">操作凭证</param>
/// <param name="user">用户</param>
/// <param name="token">取消令牌</param>
/// <returns>用户角色信息</returns>
public Task<List<UserGameRole>> GetUserGameRolesAsync(User user, CancellationToken token = default)
[ApiInformation(Cookie = CookieType.Ltoken)]
public async Task<List<UserGameRole>> GetUserGameRolesAsync(string actionTicket, Model.Entity.User user, CancellationToken token = default)
{
return GetUserGameRolesAsync(user.Entity, token);
string url = ApiEndpoints.UserGameRolesByActionTicket(actionTicket);
Response<ListWrapper<UserGameRole>>? resp = await httpClient
.SetUser(user)
.TryCatchGetFromJsonAsync<Response<ListWrapper<UserGameRole>>>(url, options, logger, token)
.ConfigureAwait(false);
return EnumerableExtension.EmptyIfNull(resp?.Data?.List);
}
/// <summary>
@@ -53,7 +63,7 @@ internal class BindingClient
{
Response<ListWrapper<UserGameRole>>? resp = await httpClient
.SetUser(user)
.TryCatchGetFromJsonAsync<Response<ListWrapper<UserGameRole>>>(ApiEndpoints.UserGameRoles, options, logger, token)
.TryCatchGetFromJsonAsync<Response<ListWrapper<UserGameRole>>>(ApiEndpoints.UserGameRolesByCookie, options, logger, token)
.ConfigureAwait(false);
return EnumerableExtension.EmptyIfNull(resp?.Data?.List);