Files
LeagueARAMTracker/LeagueAPI/APIClient.cs
2026-03-13 01:22:28 +01:00

163 lines
5.1 KiB
C#

using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using LeagueAPI.Models.Challenges;
using LeagueAPI.Models.ChampSelect;
using LeagueAPI.Models.DDragon;
using LeagueAPI.Models.DDragon.Champions;
using LeagueAPI.Utils;
namespace LeagueAPI;
public class APIClient : IDisposable
{
private const string ALL_RANDOM_ALL_CHAMPIONS = "101301";
private const string DDRAGON_BASE_URL = "https://ddragon.leagueoflegends.com";
private const int MAYHEM_QUEUE_ID = 2400;
private bool _isDisposed;
private readonly LcuHttpClient _lcuHttpClient;
private string? _latestVersion;
private readonly Dictionary<string, ChampionResponse> _championResponseCache = [];
public APIClient()
{
_lcuHttpClient = new(new LcuHttpClientHandler());
}
public async Task<Dictionary<string, LolChallengesUIChallenge>> GetAllChallengesAsync()
{
return await _lcuHttpClient.GetContentAsync<Dictionary<string, LolChallengesUIChallenge>>("/lol-challenges/v1/challenges/local-player") ?? [];
}
public async Task<int[]> GetAllRandomAllChampionsCompletedChampionsAsync()
{
Dictionary<string, LolChallengesUIChallenge> challenges = await GetAllChallengesAsync();
if (!challenges.TryGetValue(ALL_RANDOM_ALL_CHAMPIONS, out LolChallengesUIChallenge? allRandomAllChampions))
{
return [];
}
return allRandomAllChampions.CompletedIds ?? [];
}
public async Task<(IEnumerable<int> teamChampions, IEnumerable<int> benchChampions)> GetSelectableChampionIdsAsync()
{
ChampSelectSession? session = await _lcuHttpClient.GetContentAsync<ChampSelectSession>("/lol-champ-select/v1/session");
return GetSelectableChampionIds(session);
}
public static (IEnumerable<int> teamChampions, IEnumerable<int> benchChampions) GetSelectableChampionIds(ChampSelectSession? session)
{
if (session is null || !session.BenchEnabled || string.IsNullOrEmpty(session.Id))
{
return ([], []);
}
IEnumerable<int> benchChampions = session.BenchChampions.Select(b => b.ChampionId);
IEnumerable<int> teamChampions = session.MyTeam.Select(c => c.ChampionId);
return (teamChampions, benchChampions);
}
private record struct LobbyChangeGame([property: JsonPropertyName("queueId")] int QueueId);
public async Task CreateMayhemLobbyAsync()
{
await _lcuHttpClient.PostAsJsonAsync("/lol-lobby/v2/lobby", new LobbyChangeGame(MAYHEM_QUEUE_ID));
}
public async Task StartMatchmakingQueueAsync()
{
await _lcuHttpClient.PostAsJsonAsync("/lol-lobby/v2/lobby/matchmaking/search", "");
}
public async Task MatchmakingAcceptAsync()
{
await _lcuHttpClient.PostAsJsonAsync("/lol-matchmaking/v1/ready-check/accept", "");
}
#region DDragon
private static async Task<string> DDragonGetAsync(string path)
{
return await CachingHttpClient.GetStringAsync($"{DDRAGON_BASE_URL}{path}");
}
private static async Task<T?> DDragonGetAsync<T>(string path)
{
string json = await DDragonGetAsync(path);
return JsonSerializer.Deserialize<T>(json);
}
private async Task<string> GetPatch(string patch = "latest")
{
if (patch is "latest")
{
return _latestVersion ??= (await DDragonGetAsync<string[]>("/api/versions.json") ?? []).FirstOrDefault() ?? throw new Exception($"Failed to fetch version: {patch}");
}
else
{
return patch;
}
}
public async Task<ChampionData[]> GetAllChampionsAsync(string patch = "latest")
{
patch = await GetPatch(patch);
if (!_championResponseCache.TryGetValue(patch, out ChampionResponse? championResponse) || championResponse is null || championResponse.Data is null)
{
string apiUrl = $"/cdn/{patch}/data/en_US/champion.json";
championResponse = await DDragonGetAsync<ChampionResponse>(apiUrl);
if (championResponse is not null)
{
_championResponseCache[patch] = championResponse;
}
}
if (championResponse is null || championResponse.Data is null)
{
return [];
}
return [.. championResponse.Data.Values];
}
public async Task<ChampionData?> GetChampionByIdAsync(int id)
{
ChampionData[] championData = await GetAllChampionsAsync();
if (championData is not { Length: > 0 })
{
return null;
}
return championData.FirstOrDefault(c => c.Id == id);
}
#endregion
#region IDisposable
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
_lcuHttpClient?.Dispose();
}
_championResponseCache?.Clear();
_isDisposed = true;
}
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
#endregion
}