Refactor HTTP requests to use HttpHelper utility

Introduced a new HttpHelper utility to centralize and standardize HTTP requests across the codebase, replacing direct usage of HttpClient. Updated authentication, asset, game, and Mojang API logic to use the new helper, improving maintainability and consistency. Also refactored game launch options for greater flexibility and configurability.
This commit is contained in:
Gilles Lazures 2026-01-25 18:54:11 +01:00
parent 1ae8ee00db
commit 15adb39115
13 changed files with 279 additions and 102 deletions

View File

@ -212,8 +212,19 @@ class Program {
case "launcher::game":
try {
MinecraftVersion version = await GameHelper.PrepareGame("1.12.2", gameRoot, true);
GameHelper.Launch(version, _authenticatedPlayer!, gameRoot, (logLine) => {
var options = new LaunchOptions {
Version = new LaunchOptions.VersionOptions {
Number = "1.12.2",
Type = "release"
},
Memory = new LaunchOptions.MemoryOptions {
Max = $"{SettingsManager.ReadSettings().Ram.Max}M",
Min = "512M"
},
ModLoader = LaunchOptions.ModLoaderType.Forge,
};
MinecraftVersion version = await GameHelper.PrepareGame(options, gameRoot);
GameHelper.Launch(version, _authenticatedPlayer!, gameRoot, options, (logLine) => {
var logMessage = new {
requestId = "game::log",
payload = new { message = logLine.ToString() }
@ -231,6 +242,7 @@ class Program {
var response = new { requestId, payload };
window.SendWebMessage(JsonSerializer.Serialize(response, LauncherConstants._jsonOptions));
} catch (Exception ex) {
Console.WriteLine($"Error stacktrace: {ex.StackTrace}");
Console.WriteLine($"Bridge error: {ex.Message}");
}
});

View File

@ -1,11 +1,8 @@
using System.Net.Http;
using System.Text.Json;
namespace Lentia.Core.Constants
{
public static class LauncherConstants
{
public static readonly HttpClient Http = new HttpClient();
namespace Lentia.Core.Constants {
public static class LauncherConstants {
public static readonly JsonSerializerOptions _jsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
public static class Urls
{

View File

@ -1,6 +1,7 @@
using Lentia.Core.Constants;
using System.Text.Json.Serialization;
using System.Net.Http.Json;
using Lentia.Core.Utils;
namespace Lentia.Core.Auth.Yggdrasil;
@ -76,7 +77,7 @@ public class Authenticator {
};
try {
var response = await LauncherConstants.Http.PostAsJsonAsync(LauncherConstants.Urls.MojangAuthServer + "/authenticate", payload);
var response = await HttpHelper.FetchAsync(LauncherConstants.Urls.MojangAuthServer + "/authenticate", HttpMethod.Post, payload);
if (!response.IsSuccessStatusCode) {
var errorData = await response.Content.ReadFromJsonAsync<YggdrasilError>();
return AuthResult.Fail(

View File

@ -3,6 +3,7 @@ using System.Net.Http.Json;
using System.Text.Json;
using Lentia.Core.Auth.Yggdrasil;
using Lentia.Core.Constants;
using Lentia.Core.Utils;
namespace Lentia.Core.Auth.OAuth2;
@ -36,7 +37,7 @@ public class Discord {
public static async Task<AuthResult> LoginWithDiscordOAuth2(string authCode) {
var url = $"https://yggdrasil.azures.fr/auth/provider/discord/login/callback?code={authCode}&requestUser=true";
try {
var response = await LauncherConstants.Http.GetAsync(url);
var response = await HttpHelper.FetchAsync(url, HttpMethod.Get);
if (response.IsSuccessStatusCode) {
var data = await response.Content.ReadFromJsonAsync<AuthenticateResponse>();
return data != null ? AuthResult.Ok(data) : AuthResult.Fail("Erreur de lecture des données.");

View File

@ -25,7 +25,7 @@ public class AssetsHelper {
}
public static async Task<AssetsIndex> GetAssetsIndexAsync(string url) {
var response = await LauncherConstants.Http.GetAsync(url);
var response = await HttpHelper.FetchAsync(url, HttpMethod.Get);
if (response.IsSuccessStatusCode) {
string json = await response.Content.ReadAsStringAsync();
@ -86,6 +86,7 @@ public class AssetsHelper {
try {
await FileHelper.DownloadFileAsync(url, localPath);
} catch (Exception ex) {
Console.WriteLine(url);
Console.WriteLine($"Échec : {hash} - {ex.Message}");
}
});

View File

@ -1,55 +1,164 @@
using System.Diagnostics;
using System.Text.Json;
using Lentia.Core.Auth.Yggdrasil;
using Lentia.Core.Constants;
using Lentia.Core.Game.Extra;
using Lentia.Core.Utils;
using Lentia.Utils;
namespace Lentia.Core.Game;
public class LaunchOptions {
public enum ModLoaderType {
Vanilla,
Forge,
Fabric,
NeoForge
}
public VersionOptions Version { get; set; } = new();
public ModLoaderType ModLoader { get; set; } = ModLoaderType.Vanilla;
public string? Forge { get; set; }
public MemoryOptions Memory { get; set; } = new();
public string JavaPath { get; set; } = "java";
public int Timeout { get; set; } = 10000;
public List<string> CustomArgs { get; set; } = new();
public List<string> CustomLaunchArgs { get; set; } = new();
public List<string> Features { get; set; } = new();
public WindowOptions Window { get; set; } = new();
public QuickPlayOptions? QuickPlay { get; set; }
public ProxyOptions? Proxy { get; set; }
public OverridesOptions Overrides { get; set; } = new();
public class VersionOptions {
public string Number { get; set; } = "1.12.2";
public string Type { get; set; } = "release";
public string? Custom { get; set; }
}
public class MemoryOptions {
public string Max { get; set; } = "2048M";
public string Min { get; set; } = "512M";
}
public class WindowOptions {
public int? Width { get; set; }
public int? Height { get; set; }
public bool Fullscreen { get; set; } = false;
}
public class QuickPlayOptions {
public string Type { get; set; } = "singleplayer";
public string? Identifier { get; set; }
public string? Path { get; set; }
}
public class ProxyOptions {
public string? Host { get; set; }
public string Port { get; set; } = "8080";
public string? Username { get; set; }
public string? Password { get; set; }
}
public class OverridesOptions {
public string? GameDirectory { get; set; }
public string? MinecraftJar { get; set; }
public string? VersionName { get; set; }
public string? VersionJson { get; set; }
public string? Directory { get; set; }
public string? Natives { get; set; }
public string? AssetRoot { get; set; }
public string? AssetIndex { get; set; }
public string? LibraryRoot { get; set; }
public string? Cwd { get; set; }
public bool Detached { get; set; } = false;
public List<string>? Classes { get; set; }
public string? Log4jConfigurationFile { get; set; }
public UrlOverrides Url { get; set; } = new();
}
public class UrlOverrides {
public string Meta { get; set; } = "https://launchermeta.mojang.com";
public string Resource { get; set; } = "https://resources.download.minecraft.net";
public string MavenForge { get; set; } = "https://maven.minecraftforge.net/";
public string DefaultRepoForge { get; set; } = "https://libraries.minecraft.net/";
public string FallbackMaven { get; set; } = "https://search.maven.org/remotecontent?filepath=";
}
}
public static class GameHelper {
public static async Task<MinecraftVersion> PrepareGame(string targetVersion, string gameRoot, bool installForge) {
try {
string versionUrl = await VersionsHelper.GetVersionUrlAsync(targetVersion);
MinecraftVersion version = await VersionsHelper.GetVersionDetailsAsync(versionUrl);
MinecraftVersion workingVersion = version;
public static async Task<MinecraftVersion> PrepareGame(LaunchOptions options, string gameRoot) {
string root = options.Overrides.GameDirectory ?? gameRoot;
if (installForge) {
MinecraftVersion? forgeMeta = await ForgeHelper.ProcessForge(version, gameRoot);
if (forgeMeta != null) {
workingVersion = version;
}
}
AssetsIndex assetsIndex = await AssetsHelper.GetAssetsIndexAsync(version.AssetIndex!.Url!);
await AssetsHelper.DownloadAssetsParallel(assetsIndex, gameRoot);
await JavaHelper.GetJavaExecutablePath(version, gameRoot);
await VersionsHelper.DownloadClientJar(version, gameRoot);
await LibrariesHelper.DownloadLibraries(workingVersion.Libraries!, gameRoot);
LibrariesHelper.ExtractNatives(workingVersion, gameRoot);
await VersionsHelper.DownloadLoggingConfig(version, gameRoot);
return workingVersion;
} catch (Exception) {
throw;
MinecraftVersion baseVersion;
if (!string.IsNullOrEmpty(options.Overrides.VersionJson)) {
string jsonContent = await File.ReadAllTextAsync(options.Overrides.VersionJson);
baseVersion = JsonSerializer.Deserialize<MinecraftVersion>(jsonContent, LauncherConstants._jsonOptions)!;
} else {
string versionUrl = await VersionsHelper.GetVersionUrlAsync(options.Version.Number);
baseVersion = await VersionsHelper.GetVersionDetailsAsync(versionUrl);
}
MinecraftVersion workingVersion = baseVersion;
switch (options.ModLoader) {
case LaunchOptions.ModLoaderType.Forge:
var forgeMeta = await ForgeHelper.ProcessForge(baseVersion, root);
if (forgeMeta != null) {
workingVersion = baseVersion;
}
break;
}
if (baseVersion.AssetIndex == null)
throw new Exception("Erreur : L'index des assets est manquant dans le manifest de version.");
string assetRoot = options.Overrides.AssetRoot ?? Path.Combine(root, "assets");
AssetsIndex assetsIndex = await AssetsHelper.GetAssetsIndexAsync(baseVersion.AssetIndex.Url!);
await AssetsHelper.DownloadAssetsParallel(assetsIndex, assetRoot);
string libRoot = options.Overrides.LibraryRoot ?? Path.Combine(root, "libraries");
await LibrariesHelper.DownloadLibraries(workingVersion.Libraries!, libRoot);
await VersionsHelper.DownloadClientJar(baseVersion, root);
LibrariesHelper.ExtractNatives(workingVersion, root);
return workingVersion;
}
public static string BuildClasspath(MinecraftVersion version, string gameRoot) {
var paths = new List<string>();
string libRoot = Path.Combine(gameRoot, "libraries");
paths.Add(Path.Combine(gameRoot, "versions", version.Id!, $"{version.Id}.jar"));
string clientJar = Path.Combine(gameRoot, "versions", version.Id!, $"{version.Id}.jar");
if (File.Exists(clientJar)) paths.Add(clientJar);
foreach (var lib in version.Libraries!) {
if (LibrariesHelper.IsAllowed(lib.Rules, OsHelper.GetOSName())) {
string relPath = ForgeHelper.GeneratePathFromArtifactName(lib.Name!);
paths.Add(Path.Combine(libRoot, relPath));
if (version.Libraries != null) {
foreach (var lib in version.Libraries) {
if (!LibrariesHelper.IsAllowed(lib.Rules, OsHelper.GetOSName())) continue;
string? relPath = lib.Downloads?.Artifact?.Path ?? ForgeHelper.GeneratePathFromArtifactName(lib.Name!);
string fullPath = Path.Combine(libRoot, relPath);
if (File.Exists(fullPath)) {
paths.Add(fullPath);
} else {
Console.WriteLine($"[Classpath] Manquant: {fullPath}");
}
}
}
string separator = Path.PathSeparator.ToString();
return string.Join(separator, paths);
return string.Join(Path.PathSeparator.ToString(), paths);
}
public static List<string> GenerateGameArguments(MinecraftVersion version, AuthenticateResponse auth, string gameRoot) {
@ -73,52 +182,89 @@ public static class GameHelper {
return rawArgs.Split(" ", StringSplitOptions.RemoveEmptyEntries).ToList();
}
public static void Launch(MinecraftVersion version, AuthenticateResponse auth, string gameRoot, Action<string> logHandler) {
string javaPath = SettingsManager.ReadSettings().JavaPath;
public static void Launch(MinecraftVersion version, AuthenticateResponse auth, string gameRoot, LaunchOptions options, Action<string> logHandler) {
string root = options.Overrides.GameDirectory ?? gameRoot;
string nativesDir = options.Overrides.Natives ?? Path.Combine(root, "versions", version.Id!, "natives");
string javaPath = options.JavaPath ?? SettingsManager.ReadSettings().JavaPath;
string nativesDir = Path.Combine(gameRoot, "versions", version.Id!, "natives");
var jvmArgs = new List<string> {
$"-Xmx{SettingsManager.ReadSettings().Ram.Max}M",
$"-Xms{options.Memory.Min}",
$"-Xmx{options.Memory.Max}",
$"-Djava.library.path={nativesDir}",
"-Dminecraft.launcher.brand=Lentia",
"-Dminecraft.launcher.version=1.0.0"
};
// if (version.Logging?.Client?.Argument != null) {
// string logConfig = Path.Combine(gameRoot, "assets", "log_configs", version.Logging.Client.File?.Id ?? "client-log4j2.xml");
// jvmArgs.Add(version.Logging.Client.Argument.Replace("${path}", logConfig));
// string? logConfigFile = options.Overrides.Log4jConfigurationFile;
// if (string.IsNullOrEmpty(logConfigFile) && version.Logging?.Client?.Argument != null) {
// logConfigFile = Path.Combine(root, "assets", "log_configs", version.Logging.Client.File?.Id ?? "client-log4j2.xml");
// jvmArgs.Add(version.Logging.Client.Argument.Replace("${path}", logConfigFile));
// } else if (!string.IsNullOrEmpty(logConfigFile)) {
// jvmArgs.Add($"-Dlog4j.configurationFile={logConfigFile}");
// }
string classpath = BuildClasspath(version, gameRoot);
if (options.CustomArgs != null && options.CustomArgs.Any()) {
jvmArgs.AddRange(options.CustomArgs);
}
string classpath = (options.Overrides.Classes != null && options.Overrides.Classes.Any())
? string.Join(Path.PathSeparator.ToString(), options.Overrides.Classes)
: BuildClasspath(version, root);
jvmArgs.Add("-cp");
jvmArgs.Add(classpath);
jvmArgs.Add(version.MainClass ?? "net.minecraft.client.main.Main");
var gameArgs = GenerateGameArguments(version, auth, gameRoot);
jvmArgs.AddRange(gameArgs);
var gameArgs = GenerateGameArguments(version, auth, root);
if (options.QuickPlay != null) {
gameArgs.Add($"--quickPlayPath {options.QuickPlay.Path}");
gameArgs.Add($"--quickPlay{options.QuickPlay.Type} {options.QuickPlay.Identifier}");
}
if (options.Window.Fullscreen) {
gameArgs.Add("--fullscreen");
}
if (options.Window.Width.HasValue) {
gameArgs.Add("--width"); gameArgs.Add(options.Window.Width.Value.ToString());
}
if (options.Window.Height.HasValue) {
gameArgs.Add("--height"); gameArgs.Add(options.Window.Height.Value.ToString());
}
if (options.CustomLaunchArgs != null && options.CustomLaunchArgs.Any()) {
gameArgs.AddRange(options.CustomLaunchArgs);
}
var startInfo = new ProcessStartInfo(javaPath) {
WorkingDirectory = gameRoot,
Arguments = string.Join(" ", jvmArgs.Select(a => a.Contains(" ") ? $"\"{a}\"" : a)),
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
WorkingDirectory = options.Overrides.Cwd ?? root,
Arguments = string.Join(" ", jvmArgs.Concat(gameArgs).Select(a => a.Contains(" ") ? $"\"{a}\"" : a)),
UseShellExecute = options.Overrides.Detached,
RedirectStandardOutput = !options.Overrides.Detached,
RedirectStandardError = !options.Overrides.Detached,
CreateNoWindow = true
};
Console.WriteLine($"Start command: {javaPath} {startInfo.Arguments}");
var process = new Process { StartInfo = startInfo, EnableRaisingEvents = true };
process.OutputDataReceived += (s, e) => { if (e.Data != null) logHandler(e.Data); };
process.ErrorDataReceived += (s, e) => { if (e.Data != null) logHandler($"[ERROR] {e.Data}"); };
if (!options.Overrides.Detached) {
process.OutputDataReceived += (s, e) => { if (e.Data != null) logHandler(e.Data); };
process.ErrorDataReceived += (s, e) => { if (e.Data != null) logHandler($"[ERROR] {e.Data}"); };
}
process.Exited += (sender, e) => {
logHandler("GAME_CLOSED");
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (process.Start()) {
if (!options.Overrides.Detached) {
process.BeginOutputReadLine();
process.BeginErrorReadLine();
}
}
}
}

View File

@ -70,7 +70,10 @@ public static class JavaHelper {
private static async Task DownloadJavaRuntime(string root, string platform, string component) {
string allJsonUrl = "https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc6c0dba9f635e09f3900331038590632291/all.json";
var allRuntimes = await LauncherConstants.Http.GetFromJsonAsync<JsonElement>(allJsonUrl);
var allRuntimesResponse = await HttpHelper.FetchAsync(allJsonUrl);
allRuntimesResponse.EnsureSuccessStatusCode();
var allRuntimes = await allRuntimesResponse.Content.ReadFromJsonAsync<JsonElement>(LauncherConstants._jsonOptions);
if (!allRuntimes.TryGetProperty(platform, out var platformData) ||
!platformData.TryGetProperty(component, out var componentVersions)) {
@ -78,15 +81,19 @@ public static class JavaHelper {
}
string manifestUrl = componentVersions[0].GetProperty("manifest").GetProperty("url").GetString()!;
var manifest = await LauncherConstants.Http.GetFromJsonAsync<JavaRuntimeManifest>(manifestUrl);
var manifestResponse = await HttpHelper.FetchAsync(manifestUrl);
manifestResponse.EnsureSuccessStatusCode();
var manifest = await manifestResponse.Content.ReadFromJsonAsync<JavaRuntimeManifest>(LauncherConstants._jsonOptions);
string javaDir = Path.Combine(root, "runtime", component, platform);
await Parallel.ForEachAsync(manifest!.Files!, new ParallelOptions { MaxDegreeOfParallelism = 8 }, async (entry, token) => {
string localPath = Path.Combine(javaDir, entry.Key);
if (entry.Value.Type == "directory") {
Directory.CreateDirectory(localPath);
} else if (entry.Value.Downloads?.Raw != null) {
var download = entry.Value.Downloads.Raw;
if (!File.Exists(localPath) || new FileInfo(localPath).Length != download.Size) {
await FileHelper.DownloadFileAsync(download.Url!, localPath);
}

View File

@ -7,7 +7,7 @@ public static class LibrariesHelper {
public static async Task DownloadLibraries(List<Library> libraries, string root) {
string osName = OsHelper.GetOSName();
string librariesDir = Path.Combine(root, "libraries");
string librariesDir = Path.Combine(root);
var downloadsToProcess = new List<DownloadInfo>();

View File

@ -196,7 +196,7 @@ public class JavaVersionInfo {
public static class VersionsHelper {
public static async Task<string> GetVersionUrlAsync(string targetVersion) {
var response = await LauncherConstants.Http.GetAsync("https://piston-meta.mojang.com/mc/game/version_manifest_v2.json");
var response = await HttpHelper.FetchAsync("https://piston-meta.mojang.com/mc/game/version_manifest_v2.json", HttpMethod.Get);
var manifest = await response.Content.ReadFromJsonAsync<VersionManifestV2>();
var versionEntry = manifest?.Versions?.FirstOrDefault(v => v.Id == targetVersion);
@ -206,7 +206,7 @@ public static class VersionsHelper {
}
public static async Task<MinecraftVersion> GetVersionDetailsAsync(string versionUrl) {
var response = await LauncherConstants.Http.GetAsync(versionUrl);
var response = await HttpHelper.FetchAsync(versionUrl, HttpMethod.Get);
if (response.IsSuccessStatusCode) {
string jsonResponse = await response.Content.ReadAsStringAsync();

View File

@ -16,9 +16,11 @@ public static class ForgeHelper {
public static async Task<string> FetchAndDownloadForge(string mcVersion, string root, bool recommended = true) {
string promoUrl = "https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json";
LauncherConstants.Http.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
var response = await HttpHelper.FetchAsync(promoUrl, HttpMethod.Get);
var promoData = await LauncherConstants.Http.GetFromJsonAsync<ForgePromotions>(promoUrl);
response.EnsureSuccessStatusCode();
var promoData = await response.Content.ReadFromJsonAsync<ForgePromotions>(LauncherConstants._jsonOptions);
string promoKey = $"{mcVersion}-{(recommended ? "recommended" : "latest")}";
if (promoData?.Promos == null || !promoData.Promos.TryGetValue(promoKey, out string? buildVersion)) {

View File

@ -1,5 +1,3 @@
using Lentia.Core.Constants;
namespace Lentia.Core.Utils;
public static class FileHelper {
@ -13,7 +11,7 @@ public static class FileHelper {
File.Delete(destinationPath);
}
using var response = await LauncherConstants.Http.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
using var response = await HttpHelper.FetchAsync(url);
response.EnsureSuccessStatusCode();
using var streamToReadFrom = await response.Content.ReadAsStreamAsync();

View File

@ -0,0 +1,32 @@
using System.Net.Http.Json;
using Lentia.Core.Constants;
namespace Lentia.Core.Utils;
public static class HttpHelper {
private static readonly HttpClient Http = new HttpClient();
public static async Task<HttpResponseMessage> FetchAsync(string url, HttpMethod? method = null, object? body = null, Dictionary<string, string>? headers = null) {
var request = new HttpRequestMessage(method ?? HttpMethod.Get, url);
request.Headers.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
if (headers != null) {
foreach (var header in headers) {
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
}
if (body != null) {
if (body is string s) {
request.Content = new StringContent(s, System.Text.Encoding.UTF8, "application/json");
} else {
request.Content = JsonContent.Create(body, options: LauncherConstants._jsonOptions);
}
}
return await Http.SendAsync(request);
}
}

View File

@ -1,27 +1,23 @@
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using Lentia.Core.Constants;
using Lentia.Core.Utils;
namespace Lentia.Utils;
public static class MojangAPI {
public static async Task<string> UploadSkinAsync(string filePath, string variant, string token) {
LauncherConstants.Http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
using var content = new MultipartFormDataContent();
content.Add(new StringContent(variant), "variant");
byte[] fileBytes = await File.ReadAllBytesAsync(filePath);
var fileContent = new ByteArrayContent(fileBytes);
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");
content.Add(fileContent, "file", Path.GetFileName(filePath));
var response = await LauncherConstants.Http.PostAsync("https://yggdrasil.azures.fr/minecraftservices/minecraft/profile/skins", content);
var response = await HttpHelper.FetchAsync("https://yggdrasil.azures.fr/minecraftservices/minecraft/profile/skins", method: HttpMethod.Post, body: content, headers: new() { { "Authorization", $"Bearer {token}" } } );
if (response.IsSuccessStatusCode) {
return await response.Content.ReadAsStringAsync();
} else {
@ -29,12 +25,8 @@ public static class MojangAPI {
}
}
public static async Task<object> GetPlayerProfileAsync(string accessToken) {
LauncherConstants.Http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
LauncherConstants.Http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await LauncherConstants.Http.GetAsync("https://yggdrasil.azures.fr/minecraftservices/minecraft/profile");
var response = await HttpHelper.FetchAsync("https://yggdrasil.azures.fr/minecraftservices/minecraft/profile", headers: new() { { "Authorization", $"Bearer {accessToken}" }, { "Accept", "application/json" } } );
if (response.IsSuccessStatusCode) {
string jsonResponse = await response.Content.ReadAsStringAsync();
@ -45,9 +37,7 @@ public static class MojangAPI {
}
public static async Task<object> HideCapeAsync(string accessToken) {
LauncherConstants.Http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var response = await LauncherConstants.Http.DeleteAsync("https://yggdrasil.azures.fr/minecraftservices/minecraft/profile/capes/active");
var response = await HttpHelper.FetchAsync("https://yggdrasil.azures.fr/minecraftservices/minecraft/profile/capes/active", method: HttpMethod.Delete, headers: new() { { "Authorization", $"Bearer {accessToken}" } } );
if (response.IsSuccessStatusCode) {
string jsonResponse = await response.Content.ReadAsStringAsync();
@ -58,13 +48,7 @@ public static class MojangAPI {
}
public static async Task<object> ShowCapeAsync(string accessToken, string capeId) {
LauncherConstants.Http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var body = new { capeId = capeId };
string jsonBody = JsonSerializer.Serialize(body);
var content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
var response = await LauncherConstants.Http.PutAsync("https://yggdrasil.azures.fr/minecraftservices/minecraft/profile/capes/active", content);
var response = await HttpHelper.FetchAsync("https://yggdrasil.azures.fr/minecraftservices/minecraft/profile/capes/active", method: HttpMethod.Put, body: new { capeId = capeId }, headers: new() { { "Authorization", $"Bearer {accessToken}" } } );
if (response.IsSuccessStatusCode) {
string jsonResponse = await response.Content.ReadAsStringAsync();
@ -75,18 +59,14 @@ public static class MojangAPI {
}
public static async Task<object> ChangeUsernameAsync(string newName, string accessToken) {
LauncherConstants.Http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var url = $"https://yggdrasil.azures.fr/minecraftservices/minecraft/profile/name/{newName}";
var request = new HttpRequestMessage(HttpMethod.Put, url);
var response = await LauncherConstants.Http.SendAsync(request);
var response = await HttpHelper.FetchAsync(url, method: HttpMethod.Put, headers: new() { { "Authorization", $"Bearer {accessToken}" } } );
if (response.IsSuccessStatusCode) {
string jsonResponse = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<object>(jsonResponse, LauncherConstants._jsonOptions)!;
}
else {
} else {
throw new Exception($"Erreur lors du changement de pseudo (Code: {response.StatusCode})");
}
}