Support get avatars info from hoyolab dev calc & add some apis

This commit is contained in:
Xhichn
2023-03-14 16:02:10 +08:00
parent 934fb75fa5
commit 64c020a5fb
3 changed files with 131 additions and 8 deletions

View File

@@ -1,6 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.EntityFrameworkCore.Sqlite.Query.Internal;
using Microsoft.UI.Xaml;
using Snap.Hutao.Model.Primitive;
using Snap.Hutao.Service.Game;
using Snap.Hutao.Web.Hoyolab;
@@ -23,6 +25,53 @@ internal static class ApiOsEndpoints
/// <returns>用户游戏角色字符串</returns>
public const string UserGameRolesByCookie = $"{ApiOsTaKumiBindingApi}/getUserGameRolesByCookie?game_biz=hk4e_global";
/// <summary>
/// 用户游戏角色
/// </summary>
/// <param name="region">地区代号</param>
/// <returns>用户游戏角色字符串</returns>
public static string UserGameRolesByLtoken(string region)
{
return $"{ApiAccountOsBindingApi}/getUserGameRolesByLtoken?game_biz=hk4e_global&region={region}";
}
#endregion
#region SgPublicApi
public const string CalculateFurnitureCompute = $"{SgPublicApi}/event/calculateos/furniture/list";
/// <summary>
/// 计算器角色列表 size 20
/// </summary>
public const string CalculateOsAvatarList = $"{SgPublicApi}/event/calculateos/avatar/list";
/// <summary>
/// 计算器武器列表 size 20
/// </summary>
public const string CalculateOsWeaponList = $"{SgPublicApi}/event/calculateos/weapon/list";
/// <summary>
/// 计算器结果
/// </summary>
public const string CalculateOsCompute = $"{SgPublicApi}/event/calculateos/compute";
/// <summary>
/// 计算器同步角色详情 size 20
/// </summary>
/// <param name="avatarId">角色Id</param>
/// <param name="uid">uid</param>
/// <returns>角色详情</returns>
public static string CalculateOsSyncAvatarDetail(AvatarId avatarId, PlayerUid uid)
{
return $"{SgPublicApi}/event/calculateos/sync/avatar/detail?avatar_id={avatarId.Value}&uid={uid.Value}&region={uid.Region}";
}
/// <summary>
/// 计算器同步角色列表 size 20
/// </summary>
public const string CalculateOsSyncAvatarList = $"{SgPublicApi}/event/calculateos/sync/avatar/list";
#endregion
#region BbsApiOsApi
@@ -98,6 +147,30 @@ internal static class ApiOsEndpoints
}
#endregion
#region PassportApi
/// <summary>
/// Hoyolab App Login api
/// Can fetch stoken
/// </summary>
public const string WebLoginByPassword = $"{ApiAcountOsAuthApi}/webLoginByPassword";
/// <summary>
/// 获取 Ltoken
/// </summary>
public const string AccountGetLtokenByStoken = $"{ApiAcountOsAuthApi}/getLTokenBySToken";
/// <summary>
/// fetch CookieToken
/// </summary>
public const string AccountGetCookieTokenBySToken = $"{ApiAcountOsAuthApi}/getCookieAccountInfoBySToken";
/// <summary>
/// ActionTicket
/// </summary>
public const string AccountGetActionTicketBySToken = $"{ApiAcountOsAuthApi}/getActionTicketBySToken";
#endregion
#region SdkStaticLauncherApi
/// <summary>
@@ -115,6 +188,10 @@ internal static class ApiOsEndpoints
private const string ApiOsTaKumi = "https://api-os-takumi.hoyoverse.com";
private const string ApiOsTaKumiBindingApi = $"{ApiOsTaKumi}/binding/api";
private const string ApiAccountOs = "https://api-account-os.hoyolab.com";
private const string ApiAccountOsBindingApi = $"{ApiAccountOs}/binding/api";
private const string ApiAcountOsAuthApi = $"{ApiAccountOs}/account/auth/api";
private const string BbsApiOs = "https://bbs-api-os.hoyolab.com";
private const string BbsApiOsGameRecordApi = $"{BbsApiOs}/game_record/genshin/api";
@@ -123,5 +200,14 @@ internal static class ApiOsEndpoints
private const string SdkOsStatic = "https://sdk-os-static.mihoyo.com";
private const string SdkOsStaticLauncherApi = $"{SdkOsStatic}/hk4e_global/mdk/launcher/api";
private const string SgPublicApi = "https://sg-public-api.hoyolab.com";
/// <summary>
/// Web static referer
/// </summary>
public const string WebStaticSeaMihoyoReferer = "https://webstatic-sea.mihoyo.com";
public const string ActHoyolabReferer = "https://act.hoyolab.com/";
#endregion
}

View File

@@ -59,11 +59,11 @@ internal sealed class UserClient
/// <param name="user">用户</param>
/// <param name="token">取消令牌</param>
/// <returns>详细信息</returns>
[ApiInformation(Cookie = CookieType.Stoken, Salt = SaltType.K2)]
[ApiInformation(Cookie = CookieType.Ltoken, Salt = SaltType.OS)]
public async Task<Response<UserFullInfoWrapper>> GetOsUserFullInfoAsync(Model.Entity.User user, CancellationToken token = default)
{
Response<UserFullInfoWrapper>? resp = await httpClient
.SetUser(user, CookieType.Cookie)
.SetUser(user, CookieType.Ltoken)
.UseDynamicSecret(DynamicSecretVersion.Gen1, SaltType.OS, false)
.TryCatchGetFromJsonAsync<Response<UserFullInfoWrapper>>(ApiOsEndpoints.UserFullInfoQuery(user.Aid!), options, logger, token)
.ConfigureAwait(false);

View File

@@ -43,11 +43,24 @@ internal sealed class CalculateClient
[ApiInformation(Cookie = CookieType.Cookie)]
public async Task<Response<Consumption>> ComputeAsync(Model.Entity.User user, AvatarPromotionDelta delta, CancellationToken token = default)
{
Response<Consumption>? resp = await httpClient
Response<Consumption>? resp;
// TODO 添加用于判断国际服用户的 flag
if (user.Stoken == null)
{
resp = await httpClient
.SetUser(user, CookieType.Cookie)
.SetReferer(ApiOsEndpoints.ActHoyolabReferer)
.TryCatchPostAsJsonAsync<AvatarPromotionDelta, Response<Consumption>>(ApiOsEndpoints.CalculateOsCompute, delta, options, logger, token)
.ConfigureAwait(false);
}
else
{
resp = await httpClient
.SetUser(user, CookieType.Cookie)
.SetReferer(ApiEndpoints.WebStaticMihoyoReferer)
.TryCatchPostAsJsonAsync<AvatarPromotionDelta, Response<Consumption>>(ApiEndpoints.CalculateCompute, delta, options, logger, token)
.ConfigureAwait(false);
}
return Response.Response.DefaultIfNull(resp);
}
@@ -65,14 +78,28 @@ internal sealed class CalculateClient
List<Avatar> avatars = new();
Response<ListWrapper<Avatar>>? resp;
httpClient.SetUser(userAndUid.User, CookieType.CookieToken);
// 根据 uid 所属服务器选择 referer 与 api
string referer = ApiOsEndpoints.ActHoyolabReferer;
string endpoint = ApiOsEndpoints.CalculateOsSyncAvatarList;
if (userAndUid.Uid.Region == "cn_gf01" || userAndUid.Uid.Region == "cn_qd01")
{
referer = ApiEndpoints.WebStaticMihoyoReferer;
endpoint = ApiEndpoints.CalculateSyncAvatarList;
httpClient.SetUser(userAndUid.User, CookieType.CookieToken);
}
else
{
httpClient.SetUser(userAndUid.User, CookieType.Cookie);
}
do
{
filter.Page = currentPage++;
resp = await httpClient
.SetReferer(ApiEndpoints.WebStaticMihoyoReferer)
.TryCatchPostAsJsonAsync<SyncAvatarFilter, Response<ListWrapper<Avatar>>>(ApiEndpoints.CalculateSyncAvatarList, filter, options, logger, token)
.SetReferer(referer)
.TryCatchPostAsJsonAsync<SyncAvatarFilter, Response<ListWrapper<Avatar>>>(endpoint, filter, options, logger, token)
.ConfigureAwait(false);
if (resp != null && resp.IsOk())
@@ -101,11 +128,21 @@ internal sealed class CalculateClient
/// <returns>角色详情</returns>
public async Task<Response<AvatarDetail>> GetAvatarDetailAsync(UserAndUid userAndUid, Avatar avatar, CancellationToken token = default)
{
Response<AvatarDetail>? resp = await httpClient
Response<AvatarDetail>? resp;
if (userAndUid.Uid.Region == "cn_gf01" || userAndUid.Uid.Region == "cn_qd01")
{
resp = await httpClient
.SetUser(userAndUid.User, CookieType.CookieToken)
.TryCatchGetFromJsonAsync<Response<AvatarDetail>>(ApiEndpoints.CalculateSyncAvatarDetail(avatar.Id, userAndUid.Uid.Value), options, logger, token)
.ConfigureAwait(false);
}
else
{
resp = await httpClient
.SetUser(userAndUid.User, CookieType.Cookie)
.TryCatchGetFromJsonAsync<Response<AvatarDetail>>(ApiOsEndpoints.CalculateOsSyncAvatarDetail(avatar.Id, userAndUid.Uid.Value), options, logger, token)
.ConfigureAwait(false);
}
return Response.Response.DefaultIfNull(resp);
}