From 5dd4c52d9c2dfa3e127e50d473716a0db10d67e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Pivo=C5=88ka?= Date: Mon, 23 Dec 2024 05:10:21 +0100 Subject: [PATCH] Add CGameCtnChallenge option --- .../NadeoServicesExtensions.cs | 147 ++++++++++++++++-- 1 file changed, 137 insertions(+), 10 deletions(-) diff --git a/Src/ManiaAPI.NadeoAPI.Extensions.Gbx/NadeoServicesExtensions.cs b/Src/ManiaAPI.NadeoAPI.Extensions.Gbx/NadeoServicesExtensions.cs index 2cb24d3..04432dd 100644 --- a/Src/ManiaAPI.NadeoAPI.Extensions.Gbx/NadeoServicesExtensions.cs +++ b/Src/ManiaAPI.NadeoAPI.Extensions.Gbx/NadeoServicesExtensions.cs @@ -1,9 +1,8 @@ -using GBX.NET.Engines.Game; +using GBX.NET; +using GBX.NET.Engines.Game; using ManiaAPI.NadeoAPI.JsonContexts; -using System.Diagnostics; using System.Net.Http.Json; using System.Text; -using System.Text.Json; using TmEssentials; namespace ManiaAPI.NadeoAPI.Extensions.Gbx; @@ -33,9 +32,7 @@ public static async Task UploadMapAsync(this INadeoServices services, S using var content = CreateContent(bufferedStream, fileName); - using var response = await services.SendAsync(HttpMethod.Post, "maps/", content, cancellationToken); - - return await response.Content.ReadFromJsonAsync(NadeoAPIJsonContext.Default.MapInfo, cancellationToken) ?? throw new Exception("This shouldn't be null."); + return await UploadMapAsync(services, content, cancellationToken); } /// @@ -69,6 +66,67 @@ public static async Task UploadMapAsync(this INadeoServices services, s return await UploadMapAsync(services, stream, Path.GetFileName(filePath), cancellationToken); } + /// + /// Does not work with . + /// + /// + /// + /// + /// + /// + /// + /// Author login is invalid. + /// + public static async Task UploadMapAsync(this INadeoServices services, Gbx mapGbx, GbxWriteSettings settings = default, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(mapGbx); + + if (string.IsNullOrWhiteSpace(mapGbx.FilePath)) + { + throw new ArgumentException("The file path in Gbx is invalid.", nameof(mapGbx)); + } + + await using var stream = new MemoryStream(); + mapGbx.Save(stream, settings); + stream.Position = 0; + + using var content = CreateContent(stream, Path.GetFileName(mapGbx.FilePath), mapGbx.Node); + + return await UploadMapAsync(services, content, cancellationToken); + } + + /// + /// Does not work with . + /// + /// + /// + /// + /// + /// + /// + /// + /// Author login is invalid. + /// + public static async Task UploadMapAsync(this INadeoServices services, CGameCtnChallenge map, string fileName, GbxWriteSettings settings = default, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(map); + ArgumentNullException.ThrowIfNull(fileName); + + await using var stream = new MemoryStream(); + map.Save(stream, settings); + stream.Position = 0; + + using var content = CreateContent(stream, fileName, map); + + return await UploadMapAsync(services, content, cancellationToken); + } + + private static async Task UploadMapAsync(INadeoServices services, MultipartFormDataContent content, CancellationToken cancellationToken) + { + using var response = await services.SendAsync(HttpMethod.Post, "maps/", content, cancellationToken); + return await response.Content.ReadFromJsonAsync(NadeoAPIJsonContext.Default.MapInfo, cancellationToken) ?? throw new Exception("This shouldn't be null."); + } + /// /// Does not work with . /// @@ -90,9 +148,7 @@ public static async Task UpdateMapAsync(this INadeoServices services, G using var content = CreateContent(bufferedStream, fileName); - using var response = await services.SendAsync(HttpMethod.Post, $"maps/{mapId}", content, cancellationToken); - - return await response.Content.ReadFromJsonAsync(NadeoAPIJsonContext.Default.MapInfo, cancellationToken) ?? throw new Exception("This shouldn't be null."); + return await UpdateMapAsync(services, mapId, content, cancellationToken); } /// @@ -124,16 +180,87 @@ public static async Task UpdateMapAsync(this INadeoServices services, G /// public static async Task UpdateMapAsync(this INadeoServices services, Guid mapId, string filePath, CancellationToken cancellationToken = default) { + ArgumentException.ThrowIfNullOrEmpty(filePath); + await using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous); return await UpdateMapAsync(services, mapId, stream, Path.GetFileName(filePath), cancellationToken); } + /// + /// Does not work with . + /// + /// + /// + /// + /// + /// + /// + /// + /// Author login is invalid. + /// + public static async Task UpdateMapAsync(this INadeoServices services, Guid mapId, Gbx mapGbx, GbxWriteSettings settings = default, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(mapGbx); + + if (string.IsNullOrWhiteSpace(mapGbx.FilePath)) + { + throw new ArgumentException("The file path in Gbx is invalid.", nameof(mapGbx)); + } + + await using var stream = new MemoryStream(); + mapGbx.Save(stream, settings); + stream.Position = 0; + + using var content = CreateContent(stream, Path.GetFileName(mapGbx.FilePath), mapGbx.Node); + + return await UpdateMapAsync(services, mapId, content, cancellationToken); + } + + /// + /// Does not work with . + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// Author login is invalid. + /// + public static async Task UpdateMapAsync(this INadeoServices services, Guid mapId, CGameCtnChallenge map, string fileName, GbxWriteSettings settings = default, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(map); + ArgumentNullException.ThrowIfNull(fileName); + + await using var stream = new MemoryStream(); + map.Save(stream, settings); + stream.Position = 0; + + using var content = CreateContent(stream, fileName, map); + + return await UpdateMapAsync(services, mapId, content, cancellationToken); + } + + private static async Task UpdateMapAsync(INadeoServices services, Guid mapId, MultipartFormDataContent content, CancellationToken cancellationToken) + { + using var response = await services.SendAsync(HttpMethod.Post, $"maps/{mapId}", content, cancellationToken); + return await response.Content.ReadFromJsonAsync(NadeoAPIJsonContext.Default.MapInfo, cancellationToken) ?? throw new Exception("This shouldn't be null."); + } + + private static MultipartFormDataContent CreateContent(BufferedStream bufferedStream, string fileName) { var map = GBX.NET.Gbx.ParseHeaderNode(bufferedStream); bufferedStream.Position = 0; + return CreateContent(bufferedStream, fileName, map); + } + + private static MultipartFormDataContent CreateContent(Stream stream, string fileName, CGameCtnChallenge map) + { return new MultipartFormDataContent { { new StringContent(map.AuthorTime?.TotalMilliseconds.ToString() ?? "-1"), "authorScore" }, @@ -147,7 +274,7 @@ private static MultipartFormDataContent CreateContent(BufferedStream bufferedStr { new StringContent(map.MapUid), "mapUid" }, { new StringContent(map.MapName), "name" }, { new StringContent(@"{""isPlayable"":true}", Encoding.UTF8, "application/json"), "nadeoservices-core-parameters" }, - { new StreamContent(bufferedStream), "data", fileName } + { new StreamContent(stream), "data", fileName } }; } }