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);
}