mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Support sync from hoyolab my characters
This commit is contained in:
@@ -90,48 +90,72 @@ internal sealed class AvatarInfoDbOperation
|
||||
.ToList();
|
||||
EnsureItemsAvatarIdDistinct(ref dbInfos, uid);
|
||||
|
||||
GameRecordClient gameRecordClient = Ioc.Default.GetRequiredService<GameRecordClient>();
|
||||
Response<RecordPlayerInfo> playerInfoResponse = await gameRecordClient
|
||||
.GetPlayerInfoAsync(userAndUid, token)
|
||||
.ConfigureAwait(false);
|
||||
Response<RecordPlayerInfo> playerInfoResponse;
|
||||
Response<Web.Hoyolab.Takumi.GameRecord.Avatar.CharacterWrapper> charactersResponse;
|
||||
|
||||
if (userAndUid.Uid.Region == "cn_gf01" || userAndUid.Uid.Region == "cn_qd01")
|
||||
{
|
||||
GameRecordClient gameRecordClient = Ioc.Default.GetRequiredService<GameRecordClient>();
|
||||
playerInfoResponse = await gameRecordClient
|
||||
.GetPlayerInfoAsync(userAndUid, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (!playerInfoResponse.IsOk())
|
||||
{
|
||||
return GetDbAvatarInfos(uid);
|
||||
}
|
||||
|
||||
charactersResponse = await gameRecordClient
|
||||
.GetCharactersAsync(userAndUid, playerInfoResponse.Data, token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameRecordClientOs gameRecordClientOs = Ioc.Default.GetRequiredService<GameRecordClientOs>();
|
||||
playerInfoResponse = await gameRecordClientOs
|
||||
.GetPlayerInfoAsync(userAndUid, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (!playerInfoResponse.IsOk())
|
||||
{
|
||||
return GetDbAvatarInfos(uid);
|
||||
}
|
||||
|
||||
charactersResponse = await gameRecordClientOs
|
||||
.GetCharactersAsync(userAndUid, playerInfoResponse.Data, token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
if (playerInfoResponse.IsOk())
|
||||
if (charactersResponse.IsOk())
|
||||
{
|
||||
Response<Web.Hoyolab.Takumi.GameRecord.Avatar.CharacterWrapper> charactersResponse = await gameRecordClient
|
||||
.GetCharactersAsync(userAndUid, playerInfoResponse.Data, token)
|
||||
.ConfigureAwait(false);
|
||||
List<RecordCharacter> characters = charactersResponse.Data.Avatars;
|
||||
|
||||
if (charactersResponse.IsOk())
|
||||
GameRecordCharacterAvatarInfoComposer composer = Ioc.Default.GetRequiredService<GameRecordCharacterAvatarInfoComposer>();
|
||||
|
||||
foreach (RecordCharacter character in characters)
|
||||
{
|
||||
List<RecordCharacter> characters = charactersResponse.Data.Avatars;
|
||||
|
||||
GameRecordCharacterAvatarInfoComposer composer = Ioc.Default.GetRequiredService<GameRecordCharacterAvatarInfoComposer>();
|
||||
|
||||
foreach (RecordCharacter character in characters)
|
||||
if (AvatarIds.IsPlayer(character.Id))
|
||||
{
|
||||
if (AvatarIds.IsPlayer(character.Id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
ModelAvatarInfo? entity = dbInfos.SingleOrDefault(i => i.Info.AvatarId == character.Id);
|
||||
ModelAvatarInfo? entity = dbInfos.SingleOrDefault(i => i.Info.AvatarId == character.Id);
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
EnkaAvatarInfo avatarInfo = new() { AvatarId = character.Id };
|
||||
avatarInfo = await composer.ComposeAsync(avatarInfo, character).ConfigureAwait(false);
|
||||
entity = ModelAvatarInfo.Create(uid, avatarInfo);
|
||||
appDbContext.AvatarInfos.AddAndSave(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.Info = await composer.ComposeAsync(entity.Info, character).ConfigureAwait(false);
|
||||
appDbContext.AvatarInfos.UpdateAndSave(entity);
|
||||
}
|
||||
if (entity == null)
|
||||
{
|
||||
EnkaAvatarInfo avatarInfo = new() { AvatarId = character.Id };
|
||||
avatarInfo = await composer.ComposeAsync(avatarInfo, character).ConfigureAwait(false);
|
||||
entity = ModelAvatarInfo.Create(uid, avatarInfo);
|
||||
appDbContext.AvatarInfos.AddAndSave(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.Info = await composer.ComposeAsync(entity.Info, character).ConfigureAwait(false);
|
||||
appDbContext.AvatarInfos.UpdateAndSave(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,24 @@ internal sealed class GameRecordClientOs
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取玩家基础信息
|
||||
/// </summary>
|
||||
/// <param name="userAndUid">用户与角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>玩家的基础信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.Ltoken, Salt = SaltType.OS)]
|
||||
public async Task<Response<PlayerInfo>> GetPlayerInfoAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
Response<PlayerInfo>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.Cookie)
|
||||
.UseDynamicSecret(DynamicSecretVersion.Gen1, SaltType.OS, false)
|
||||
.TryCatchGetFromJsonAsync<Response<PlayerInfo>>(ApiOsEndpoints.GameRecordIndex(userAndUid.Uid), options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取玩家深渊信息
|
||||
/// </summary>
|
||||
@@ -46,7 +64,6 @@ internal sealed class GameRecordClientOs
|
||||
[ApiInformation(Cookie = CookieType.Cookie, Salt = SaltType.OS)]
|
||||
public async Task<Response<SpiralAbyss.SpiralAbyss>> GetSpiralAbyssAsync(UserAndUid userAndUid, SpiralAbyssSchedule schedule, CancellationToken token = default)
|
||||
{
|
||||
System.Net.Http.Headers.HttpRequestHeaders headers = httpClient.DefaultRequestHeaders;
|
||||
Response<SpiralAbyss.SpiralAbyss>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.Cookie)
|
||||
.UseDynamicSecret(DynamicSecretVersion.Gen1, SaltType.OS, false)
|
||||
@@ -55,4 +72,44 @@ internal sealed class GameRecordClientOs
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取玩家角色详细信息
|
||||
/// </summary>
|
||||
/// <param name="userAndUid">用户与角色</param>
|
||||
/// <param name="playerInfo">玩家的基础信息</param>
|
||||
/// <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)
|
||||
{
|
||||
CharacterData data = new(userAndUid.Uid, playerInfo.Avatars.Select(x => x.Id));
|
||||
|
||||
Response<CharacterWrapper>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.Cookie)
|
||||
.UseDynamicSecret(DynamicSecretVersion.Gen1, SaltType.OS, false)
|
||||
.TryCatchPostAsJsonAsync<CharacterData, Response<CharacterWrapper>>(ApiOsEndpoints.GameRecordCharacter, data, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
private class CharacterData
|
||||
{
|
||||
public CharacterData(PlayerUid uid, IEnumerable<AvatarId> characterIds)
|
||||
{
|
||||
CharacterIds = characterIds;
|
||||
Uid = uid.Value;
|
||||
Server = uid.Region;
|
||||
}
|
||||
|
||||
[JsonPropertyName("character_ids")]
|
||||
public IEnumerable<AvatarId> CharacterIds { get; }
|
||||
|
||||
[JsonPropertyName("role_id")]
|
||||
public string Uid { get; }
|
||||
|
||||
[JsonPropertyName("server")]
|
||||
public string Server { get; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user