mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-21 09:45:48 +08:00
104 lines
4.7 KiB
C#
104 lines
4.7 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using BetterGenshinImpact.Helpers.Http;
|
|
using BetterGenshinImpact.GameTask;
|
|
using BetterGenshinImpact.GameTask.MapMask;
|
|
using BetterGenshinImpact.Service.Interface;
|
|
using BetterGenshinImpact.Service.Model.MihoyoMap.Requests;
|
|
using BetterGenshinImpact.Service.Model.MihoyoMap.Responses;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace BetterGenshinImpact.Service;
|
|
|
|
public class HoYoLabMapApiService : IHoYoLabMapApiService
|
|
{
|
|
private readonly HttpClient _httpClient;
|
|
private const string TreeEndpoint = "https://sg-public-api-static.hoyolab.com/common/map_user/ys_obc/v2/map/label/tree";
|
|
private const string ListEndpoint = "https://sg-public-api-static.hoyolab.com/common/map_user/ys_obc/v3/map/point/list";
|
|
private const string InfoEndpoint = "https://sg-public-api-static.hoyolab.com/common/map_user/ys_obc/v1/map/point/info";
|
|
private const string DefaultLang = MapMaskConfig.HoYoLabLanguageEnUs;
|
|
|
|
public HoYoLabMapApiService()
|
|
{
|
|
_httpClient = HttpClientFactory.GetCommonSendClient();
|
|
}
|
|
|
|
private static HttpRequestMessage CreateRequest(HttpMethod method, string url)
|
|
{
|
|
var request = new HttpRequestMessage(method, url);
|
|
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
request.Headers.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36");
|
|
request.Headers.Referrer = new Uri("https://act.hoyolab.com/");
|
|
return request;
|
|
}
|
|
|
|
private static T DeserializeRequired<T>(string json)
|
|
{
|
|
var result = JsonConvert.DeserializeObject<T>(json);
|
|
if (result == null)
|
|
{
|
|
throw new JsonException($"Failed to deserialize {typeof(T).Name}. The API returned an empty or invalid JSON.");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static string NormalizeLanguage(string? lang)
|
|
{
|
|
var normalized = (lang ?? string.Empty).Trim().Replace('_', '-').Replace(' ', '-').ToLowerInvariant();
|
|
return normalized switch
|
|
{
|
|
MapMaskConfig.HoYoLabLanguagePtPt => MapMaskConfig.HoYoLabLanguagePtPt,
|
|
MapMaskConfig.HoYoLabLanguageEsEs => MapMaskConfig.HoYoLabLanguageEsEs,
|
|
MapMaskConfig.HoYoLabLanguageEnUs => MapMaskConfig.HoYoLabLanguageEnUs,
|
|
_ => DefaultLang
|
|
};
|
|
}
|
|
|
|
private static string GetCurrentLanguage()
|
|
{
|
|
var lang = TaskContext.Instance().Config.MapMaskConfig.HoYoLabLanguage;
|
|
return NormalizeLanguage(lang);
|
|
}
|
|
|
|
public async Task<ApiResponse<LabelTreeData>> GetLabelTreeAsync(LabelTreeRequest request, CancellationToken ct = default)
|
|
{
|
|
var lang = GetCurrentLanguage();
|
|
var url = $"{TreeEndpoint}?map_id={request.MapId}&app_sn={Uri.EscapeDataString(request.AppSn)}&lang={lang}";
|
|
using var httpRequest = CreateRequest(HttpMethod.Get, url);
|
|
using var resp = await _httpClient.SendAsync(httpRequest, ct);
|
|
resp.EnsureSuccessStatusCode();
|
|
var json = await resp.Content.ReadAsStringAsync(ct);
|
|
return DeserializeRequired<ApiResponse<LabelTreeData>>(json);
|
|
}
|
|
|
|
public async Task<ApiResponse<PointInfoData>> GetPointInfoAsync(PointInfoRequest request, CancellationToken ct = default)
|
|
{
|
|
var lang = GetCurrentLanguage();
|
|
var url = $"{InfoEndpoint}?map_id={request.MapId}&point_id={request.PointId}&app_sn={Uri.EscapeDataString(request.AppSn)}&lang={lang}";
|
|
using var httpRequest = CreateRequest(HttpMethod.Get, url);
|
|
httpRequest.Headers.Add("x-rpc-map_version", "4.5");
|
|
using var resp = await _httpClient.SendAsync(httpRequest, ct);
|
|
resp.EnsureSuccessStatusCode();
|
|
var json = await resp.Content.ReadAsStringAsync(ct);
|
|
return DeserializeRequired<ApiResponse<PointInfoData>>(json);
|
|
}
|
|
|
|
public async Task<ApiResponse<PointListData>> GetPointListAsync(PointListRequest request, CancellationToken ct = default)
|
|
{
|
|
var lang = GetCurrentLanguage();
|
|
var labelIds = request.LabelIds != null && request.LabelIds.Count > 0
|
|
? string.Join(",", request.LabelIds.Select(x => x.ToString()))
|
|
: string.Empty;
|
|
var url = $"{ListEndpoint}?map_id={request.MapId}&app_sn={Uri.EscapeDataString(request.AppSn)}&lang={lang}&label_ids={Uri.EscapeDataString(labelIds)}";
|
|
using var httpRequest = CreateRequest(HttpMethod.Get, url);
|
|
using var resp = await _httpClient.SendAsync(httpRequest, ct);
|
|
resp.EnsureSuccessStatusCode();
|
|
var json = await resp.Content.ReadAsStringAsync(ct);
|
|
return DeserializeRequired<ApiResponse<PointListData>>(json);
|
|
}
|
|
} |