178 lines
5.7 KiB
C#
178 lines
5.7 KiB
C#
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using System.Text.RegularExpressions;
|
|
using CliWrap;
|
|
using CliWrap.Buffered;
|
|
using LeagueAPI.Models.Challenges;
|
|
using LeagueAPI.Models.ChampSelect;
|
|
using LeagueAPI.Models.DDragon;
|
|
using LeagueAPI.Models.DDragon.Champions;
|
|
using LeagueAPI.Utils;
|
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
|
|
|
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 readonly HttpClient _dDragonHttpClient;
|
|
|
|
private string? _latestVersion;
|
|
|
|
private readonly Dictionary<string, ChampionResponse> _championResponseCache = [];
|
|
|
|
public APIClient()
|
|
{
|
|
_lcuHttpClient = new(new LcuHttpClientHandler());
|
|
_dDragonHttpClient = new HttpClient() { BaseAddress = new Uri(DDRAGON_BASE_URL) };
|
|
}
|
|
|
|
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<int[]> GetSelectableChampionIdsAsync()
|
|
{
|
|
ChampSelectSession? session = await _lcuHttpClient.GetContentAsync<ChampSelectSession>("/lol-champ-select/v1/session");
|
|
return GetSelectableChampionIds(session);
|
|
}
|
|
|
|
public int[] GetSelectableChampionIds(ChampSelectSession? session)
|
|
{
|
|
if (session is null || !session.BenchEnabled)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
IEnumerable<int> benchChampions = session.BenchChampions.Select(b => b.ChampionId);
|
|
IEnumerable<int> teamChampions = session.MyTeam.Select(c => c.ChampionId);
|
|
|
|
return [.. benchChampions, .. teamChampions];
|
|
}
|
|
|
|
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 async Task<string> DDragonGetAsync(string path)
|
|
{
|
|
HttpResponseMessage response = await _dDragonHttpClient.GetAsync(path);
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
Command cmd = Cli.Wrap("curl")
|
|
.WithArguments($"{DDRAGON_BASE_URL}{path}");
|
|
BufferedCommandResult result = await cmd.ExecuteBufferedAsync();
|
|
return result.IsSuccess ? result.StandardOutput : throw new Exception($"Failed to fetch from Datadragon: {path}");
|
|
}
|
|
return await response.Content.ReadAsStringAsync();
|
|
}
|
|
|
|
private 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();
|
|
_dDragonHttpClient?.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
|
|
}
|