diff --git a/src/Snap.Hutao/Snap.Hutao/Web/ApiOsEndpoints.cs b/src/Snap.Hutao/Snap.Hutao/Web/ApiOsEndpoints.cs index 4dc726ac..1de4678f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/ApiOsEndpoints.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/ApiOsEndpoints.cs @@ -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 /// 用户游戏角色字符串 public const string UserGameRolesByCookie = $"{ApiOsTaKumiBindingApi}/getUserGameRolesByCookie?game_biz=hk4e_global"; + /// + /// 用户游戏角色 + /// + /// 地区代号 + /// 用户游戏角色字符串 + public static string UserGameRolesByLtoken(string region) + { + return $"{ApiAccountOsBindingApi}/getUserGameRolesByLtoken?game_biz=hk4e_global®ion={region}"; + } + + #endregion + + #region SgPublicApi + + public const string CalculateFurnitureCompute = $"{SgPublicApi}/event/calculateos/furniture/list"; + + /// + /// 计算器角色列表 size 20 + /// + public const string CalculateOsAvatarList = $"{SgPublicApi}/event/calculateos/avatar/list"; + + /// + /// 计算器武器列表 size 20 + /// + public const string CalculateOsWeaponList = $"{SgPublicApi}/event/calculateos/weapon/list"; + + /// + /// 计算器结果 + /// + public const string CalculateOsCompute = $"{SgPublicApi}/event/calculateos/compute"; + + /// + /// 计算器同步角色详情 size 20 + /// + /// 角色Id + /// uid + /// 角色详情 + public static string CalculateOsSyncAvatarDetail(AvatarId avatarId, PlayerUid uid) + { + return $"{SgPublicApi}/event/calculateos/sync/avatar/detail?avatar_id={avatarId.Value}&uid={uid.Value}®ion={uid.Region}"; + } + + /// + /// 计算器同步角色列表 size 20 + /// + public const string CalculateOsSyncAvatarList = $"{SgPublicApi}/event/calculateos/sync/avatar/list"; + #endregion #region BbsApiOsApi @@ -98,6 +147,30 @@ internal static class ApiOsEndpoints } #endregion + #region PassportApi + + /// + /// Hoyolab App Login api + /// Can fetch stoken + /// + public const string WebLoginByPassword = $"{ApiAcountOsAuthApi}/webLoginByPassword"; + + /// + /// 获取 Ltoken + /// + public const string AccountGetLtokenByStoken = $"{ApiAcountOsAuthApi}/getLTokenBySToken"; + + /// + /// fetch CookieToken + /// + public const string AccountGetCookieTokenBySToken = $"{ApiAcountOsAuthApi}/getCookieAccountInfoBySToken"; + + /// + /// ActionTicket + /// + public const string AccountGetActionTicketBySToken = $"{ApiAcountOsAuthApi}/getActionTicketBySToken"; + #endregion + #region SdkStaticLauncherApi /// @@ -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"; + + /// + /// Web static referer + /// + public const string WebStaticSeaMihoyoReferer = "https://webstatic-sea.mihoyo.com"; + public const string ActHoyolabReferer = "https://act.hoyolab.com/"; + #endregion } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Bbs/User/UserClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Bbs/User/UserClient.cs index f09ecbbd..4daca269 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Bbs/User/UserClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Bbs/User/UserClient.cs @@ -59,11 +59,11 @@ internal sealed class UserClient /// 用户 /// 取消令牌 /// 详细信息 - [ApiInformation(Cookie = CookieType.Stoken, Salt = SaltType.K2)] + [ApiInformation(Cookie = CookieType.Ltoken, Salt = SaltType.OS)] public async Task> GetOsUserFullInfoAsync(Model.Entity.User user, CancellationToken token = default) { Response? resp = await httpClient - .SetUser(user, CookieType.Cookie) + .SetUser(user, CookieType.Ltoken) .UseDynamicSecret(DynamicSecretVersion.Gen1, SaltType.OS, false) .TryCatchGetFromJsonAsync>(ApiOsEndpoints.UserFullInfoQuery(user.Aid!), options, logger, token) .ConfigureAwait(false); diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Event/Calculate/CalculateClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Event/Calculate/CalculateClient.cs index 609796c5..7c7bea40 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Event/Calculate/CalculateClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Takumi/Event/Calculate/CalculateClient.cs @@ -43,11 +43,24 @@ internal sealed class CalculateClient [ApiInformation(Cookie = CookieType.Cookie)] public async Task> ComputeAsync(Model.Entity.User user, AvatarPromotionDelta delta, CancellationToken token = default) { - Response? resp = await httpClient + Response? resp; + // TODO 添加用于判断国际服用户的 flag + if (user.Stoken == null) + { + resp = await httpClient + .SetUser(user, CookieType.Cookie) + .SetReferer(ApiOsEndpoints.ActHoyolabReferer) + .TryCatchPostAsJsonAsync>(ApiOsEndpoints.CalculateOsCompute, delta, options, logger, token) + .ConfigureAwait(false); + } + else + { + resp = await httpClient .SetUser(user, CookieType.Cookie) .SetReferer(ApiEndpoints.WebStaticMihoyoReferer) .TryCatchPostAsJsonAsync>(ApiEndpoints.CalculateCompute, delta, options, logger, token) .ConfigureAwait(false); + } return Response.Response.DefaultIfNull(resp); } @@ -65,14 +78,28 @@ internal sealed class CalculateClient List avatars = new(); Response>? 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>>(ApiEndpoints.CalculateSyncAvatarList, filter, options, logger, token) + .SetReferer(referer) + .TryCatchPostAsJsonAsync>>(endpoint, filter, options, logger, token) .ConfigureAwait(false); if (resp != null && resp.IsOk()) @@ -101,11 +128,21 @@ internal sealed class CalculateClient /// 角色详情 public async Task> GetAvatarDetailAsync(UserAndUid userAndUid, Avatar avatar, CancellationToken token = default) { - Response? resp = await httpClient + Response? resp; + if (userAndUid.Uid.Region == "cn_gf01" || userAndUid.Uid.Region == "cn_qd01") + { + resp = await httpClient .SetUser(userAndUid.User, CookieType.CookieToken) .TryCatchGetFromJsonAsync>(ApiEndpoints.CalculateSyncAvatarDetail(avatar.Id, userAndUid.Uid.Value), options, logger, token) .ConfigureAwait(false); - + } + else + { + resp = await httpClient + .SetUser(userAndUid.User, CookieType.Cookie) + .TryCatchGetFromJsonAsync>(ApiOsEndpoints.CalculateOsSyncAvatarDetail(avatar.Id, userAndUid.Uid.Value), options, logger, token) + .ConfigureAwait(false); + } return Response.Response.DefaultIfNull(resp); }