Add HoyoPlay API

This commit is contained in:
qhy040404
2024-06-17 12:55:17 +08:00
parent a86caaf229
commit c342147809
18 changed files with 286 additions and 0 deletions

View File

@@ -45,6 +45,10 @@ internal class LaunchScheme : IEquatable<ChannelOptions>
/// </summary>
public int LauncherId { get; private protected set; }
public string HoyoPlayLauncherId { get; private protected set; }
public string HoyoPlayGameId { get; private protected set; }
/// <summary>
/// API Key
/// </summary>

View File

@@ -9,11 +9,15 @@ internal sealed class LaunchSchemeBilibili : LaunchScheme
{
private const int SdkStaticLauncherBilibiliId = 17;
private const string SdkStaticLauncherBilibiliKey = "KAtdSsoQ";
private const string HoyoPlayLauncherBilibiliId = "umfgRO5gh5";
private const string HoyoPlayGameBilibiliId = "T2S0Gz4Dr2";
public LaunchSchemeBilibili(SubChannelType subChannel, bool isNotCompatOnly = true)
{
LauncherId = SdkStaticLauncherBilibiliId;
Key = SdkStaticLauncherBilibiliKey;
HoyoPlayLauncherId = HoyoPlayLauncherBilibiliId;
HoyoPlayGameId = HoyoPlayGameBilibiliId;
Channel = ChannelType.Bili;
SubChannel = subChannel;
IsOversea = false;

View File

@@ -9,11 +9,15 @@ internal sealed class LaunchSchemeChinese : LaunchScheme
{
private const int SdkStaticLauncherChineseId = 18;
private const string SdkStaticLauncherChineseKey = "eYd89JmJ";
private const string HoyoPlayLauncherChineseId = "jGHBHlcOq1";
private const string HoyoPlayGameChineseId = "1Z8W5NHUQb";
public LaunchSchemeChinese(ChannelType channel, SubChannelType subChannel, bool isNotCompatOnly = true)
{
LauncherId = SdkStaticLauncherChineseId;
Key = SdkStaticLauncherChineseKey;
HoyoPlayLauncherId = HoyoPlayLauncherChineseId;
HoyoPlayGameId = HoyoPlayGameChineseId;
Channel = channel;
SubChannel = subChannel;
IsOversea = false;

View File

@@ -9,11 +9,15 @@ internal sealed class LaunchSchemeOversea : LaunchScheme
{
private const int SdkStaticLauncherOverseaId = 10;
private const string SdkStaticLauncherOverseaKey = "gcStgarh";
private const string HoyoPlayLauncherOverseaId = "VYTpXlbWo8";
private const string HoyoPlayGameOverseaId = "gopR6Cufr3";
public LaunchSchemeOversea(ChannelType channel, SubChannelType subChannel, bool isNotCompatOnly = true)
{
LauncherId = SdkStaticLauncherOverseaId;
Key = SdkStaticLauncherOverseaKey;
HoyoPlayLauncherId = HoyoPlayLauncherOverseaId;
HoyoPlayGameId = HoyoPlayGameOverseaId;
Channel = channel;
SubChannel = subChannel;
IsOversea = true;

View File

@@ -284,6 +284,25 @@ internal static class ApiEndpoints
#endregion
#region HoyoPlayApi
public static string HoyoPlayConnectGamePackages(LaunchScheme scheme)
{
return $"{HoyoPlayApiConnectApi}/getGamePackages?game_ids[]={scheme.HoyoPlayGameId}&launcher_id={scheme.HoyoPlayLauncherId}";
}
public static string HoyoPlayConnectGameChannelSDKs(LaunchScheme scheme)
{
return $"{HoyoPlayApiConnectApi}/getGameChannelSDKs?channel={scheme.Channel:D}&game_ids[]={scheme.HoyoPlayGameId}&launcher_id={scheme.HoyoPlayLauncherId}&sub_channel={scheme.SubChannel:D}";
}
public static string HoyoPlayConnectDeprecatedFileConfigs(LaunchScheme scheme)
{
return $"{HoyoPlayApiConnectApi}/getGameDeprecatedFileConfigs?channel={scheme.Channel:D}&game_ids[]={scheme.HoyoPlayGameId}&launcher_id={scheme.HoyoPlayLauncherId}&sub_channel={scheme.SubChannel:D}";
}
#endregion
#region PassportApi | PassportApiV4
/// <summary>
@@ -395,6 +414,9 @@ internal static class ApiEndpoints
private const string Hk4eSdk = "https://hk4e-sdk.mihoyo.com";
private const string HoyoPlayApi = "https://hyp-api.mihoyo.com";
private const string HoyoPlayApiConnectApi = $"{HoyoPlayApi}/hyp/hyp-connect/api";
private const string PassportApi = "https://passport-api.mihoyo.com";
private const string PassportApiAuthApi = $"{PassportApi}/account/auth/api";
private const string PassportApiV4 = "https://passport-api-v4.mihoyo.com";

View File

@@ -298,6 +298,25 @@ internal static class ApiOsEndpoints
}
#endregion
#region SgHoyoPlayApi
public static string SgHoyoPlayConnectGamePackages(LaunchScheme scheme)
{
return $"{SgHoyoPlayApiConnectApi}/getGamePackages?game_ids[]={scheme.HoyoPlayGameId}&launcher_id={scheme.HoyoPlayLauncherId}";
}
public static string SgHoyoPlayConnectGameChannelSDKs(LaunchScheme scheme)
{
return $"{SgHoyoPlayApiConnectApi}/getGameChannelSDKs?channel={scheme.Channel:D}&game_ids[]={scheme.HoyoPlayGameId}&launcher_id={scheme.HoyoPlayLauncherId}&sub_channel={scheme.SubChannel:D}";
}
public static string SgHoyoPlayConnectDeprecatedFileConfigs(LaunchScheme scheme)
{
return $"{SgHoyoPlayApiConnectApi}/getGameDeprecatedFileConfigs?channel={scheme.Channel:D}&game_ids[]={scheme.HoyoPlayGameId}&launcher_id={scheme.HoyoPlayLauncherId}&sub_channel={scheme.SubChannel:D}";
}
#endregion
#region SdkOsStaticLauncherApi
public static string SdkOsStaticLauncherResource(LaunchScheme scheme)
@@ -344,6 +363,9 @@ internal static class ApiOsEndpoints
private const string SgPublicApi = "https://sg-public-api.hoyoverse.com";
private const string SgHk4eApi = "https://sg-hk4e-api.hoyoverse.com";
private const string SgHoyoPlayApi = "https://sg-hyp-api.hoyoverse.com";
private const string SgHoyoPlayApiConnectApi = $"{SgHoyoPlayApi}/hyp/hyp-connect/api";
private const string WebApiOs = "https://webapi-os.account.hoyoverse.com";
private const string WebApiOsAccountApi = $"{WebApiOs}/Api";

View File

@@ -0,0 +1,19 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK;
internal sealed class ChannelSDK
{
[JsonPropertyName("channel_sdk_pkg")]
public PackageSegment ChannelSdkPackage { get; set; } = default!;
[JsonPropertyName("game")]
public GameIdentifier Game { get; set; } = default!;
[JsonPropertyName("pkg_version_file_name")]
public string PackageVersionFileName { get; set; } = default!;
[JsonPropertyName("version")]
public string Version { get; set; } = default!;
}

View File

@@ -0,0 +1,10 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK;
internal sealed class ChannelSDKs
{
[JsonPropertyName("game_channel_sdks")]
public List<ChannelSDK> GameChannelSDKs { get; set; } = default!;
}

View File

@@ -0,0 +1,10 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile;
internal sealed class DeprecatedFile
{
[JsonPropertyName("name")]
public string Name { get; set; } = default!;
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile;
internal sealed class DeprecatedFileConfig
{
[JsonPropertyName("deprecated_files")]
public List<DeprecatedFile> DeprecatedFiles { get; set; } = default!;
[JsonPropertyName("game")]
public GameIdentifier Game { get; set; } = default!;
}

View File

@@ -0,0 +1,10 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile;
internal sealed class DeprecatedFileConfigs
{
[JsonPropertyName("deprecated_file_configs")]
public List<DeprecatedFileConfig> Configs { get; set; } = default!;
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect;
internal sealed class GameIdentifier
{
[JsonPropertyName("id")]
public string Id { get; set; } = default!;
[JsonPropertyName("biz")]
public string Biz { get; set; } = default!;
}

View File

@@ -0,0 +1,74 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Service.Game.Scheme;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package;
using Snap.Hutao.Web.Request.Builder;
using Snap.Hutao.Web.Request.Builder.Abstraction;
using Snap.Hutao.Web.Response;
using System.Net.Http;
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect;
[ConstructorGenerated(ResolveHttpClient = true)]
[HttpClient(HttpClientConfiguration.Default)]
internal sealed partial class HoyoPlayClient
{
private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory;
private readonly HttpClient httpClient;
private readonly ILogger<HoyoPlayClient> logger;
public async ValueTask<Response<GamePackage>> GetPackagesAsync(LaunchScheme scheme, CancellationToken token = default)
{
string url = scheme.IsOversea
? ApiOsEndpoints.SgHoyoPlayConnectGamePackages(scheme)
: ApiEndpoints.HoyoPlayConnectGamePackages(scheme);
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(url)
.Get();
Response<GamePackage>? resp = await builder
.SendAsync<Response<GamePackage>>(httpClient, logger, token)
.ConfigureAwait(false);
return Response.Response.DefaultIfNull(resp);
}
public async ValueTask<Response<ChannelSDKs>> GetChannelSDKAsync(LaunchScheme scheme, CancellationToken token = default)
{
string url = scheme.IsOversea
? ApiOsEndpoints.SgHoyoPlayConnectGameChannelSDKs(scheme)
: ApiEndpoints.HoyoPlayConnectGameChannelSDKs(scheme);
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(url)
.Get();
Response<ChannelSDKs>? resp = await builder
.SendAsync<Response<ChannelSDKs>>(httpClient, logger, token)
.ConfigureAwait(false);
return Response.Response.DefaultIfNull(resp);
}
public async ValueTask<Response<DeprecatedFileConfigs>> GetDeprecatedFilesAsync(LaunchScheme scheme, CancellationToken token = default)
{
string url = scheme.IsOversea
? ApiOsEndpoints.SgHoyoPlayConnectDeprecatedFileConfigs(scheme)
: ApiEndpoints.HoyoPlayConnectDeprecatedFileConfigs(scheme);
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(url)
.Get();
Response<DeprecatedFileConfigs>? resp = await builder
.SendAsync<Response<DeprecatedFileConfigs>>(httpClient, logger, token)
.ConfigureAwait(false);
return Response.Response.DefaultIfNull(resp);
}
}

View File

@@ -0,0 +1,10 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package;
internal sealed class AudioPackageSegment : PackageSegment
{
[JsonPropertyName("language")]
public string Language { get; set; } = default!;
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package;
internal sealed class Game
{
[JsonPropertyName("major")]
public Package? Major { get; set; }
[JsonPropertyName("patches")]
public List<Package> Patches { get; set; } = default!;
}

View File

@@ -0,0 +1,16 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package;
internal sealed class GamePackage
{
[JsonPropertyName("game")]
public GameIdentifier Game { get; set; } = default!;
[JsonPropertyName("main")]
public Game Main { get; set; } = default!;
[JsonPropertyName("pre_download")]
public Game PreDownload { get; set; } = default!;
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package;
internal sealed class Package
{
[JsonPropertyName("version")]
public string Version { get; set; } = default!;
[JsonPropertyName("game_pkgs")]
public List<PackageSegment> GamePackages { get; set; } = default!;
[JsonPropertyName("audio_pkgs")]
public List<AudioPackageSegment> AudioPackages { get; set; } = default!;
[JsonPropertyName("res_list_url")]
public string ResListUrl { get; set; } = default!;
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect;
internal class PackageSegment
{
[JsonPropertyName("url")]
public string Url { get; set; } = default!;
[JsonPropertyName("md5")]
public string Md5 { get; set; } = default!;
[JsonPropertyName("size")]
public string Size { get; set; } = default!;
[JsonPropertyName("decompressed_size")]
public string DecompressedSize { get; set; } = default!;
}