From 8940ee5d9cb3a41a974d30ba3d3efa0dea74c751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 5 Feb 2025 11:52:43 +0100 Subject: [PATCH] Add API request & response structures for beatmap submission --- .../Online/API/Requests/APIUploadRequest.cs | 26 ++++++ .../Requests/PatchBeatmapPackageRequest.cs | 51 ++++++++++++ .../API/Requests/PutBeatmapSetRequest.cs | 82 +++++++++++++++++++ .../Requests/ReplaceBeatmapPackageRequest.cs | 45 ++++++++++ .../Responses/PutBeatmapSetResponse.cs | 30 +++++++ 5 files changed, 234 insertions(+) create mode 100644 osu.Game/Online/API/Requests/APIUploadRequest.cs create mode 100644 osu.Game/Online/API/Requests/PatchBeatmapPackageRequest.cs create mode 100644 osu.Game/Online/API/Requests/PutBeatmapSetRequest.cs create mode 100644 osu.Game/Online/API/Requests/ReplaceBeatmapPackageRequest.cs create mode 100644 osu.Game/Online/API/Requests/Responses/PutBeatmapSetResponse.cs diff --git a/osu.Game/Online/API/Requests/APIUploadRequest.cs b/osu.Game/Online/API/Requests/APIUploadRequest.cs new file mode 100644 index 0000000000..3503b4cebb --- /dev/null +++ b/osu.Game/Online/API/Requests/APIUploadRequest.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Diagnostics; +using osu.Framework.IO.Network; + +namespace osu.Game.Online.API.Requests +{ + public abstract class APIUploadRequest : APIRequest + { + protected override WebRequest CreateWebRequest() + { + var request = base.CreateWebRequest(); + request.UploadProgress += onUploadProgress; + return request; + } + + private void onUploadProgress(long current, long total) + { + Debug.Assert(API != null); + API.Schedule(() => Progressed?.Invoke(current, total)); + } + + public event APIProgressHandler? Progressed; + } +} diff --git a/osu.Game/Online/API/Requests/PatchBeatmapPackageRequest.cs b/osu.Game/Online/API/Requests/PatchBeatmapPackageRequest.cs new file mode 100644 index 0000000000..85981448da --- /dev/null +++ b/osu.Game/Online/API/Requests/PatchBeatmapPackageRequest.cs @@ -0,0 +1,51 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Net.Http; +using osu.Framework.IO.Network; + +namespace osu.Game.Online.API.Requests +{ + public class PatchBeatmapPackageRequest : APIUploadRequest + { + protected override string Uri + { + get + { + // can be removed once the service has been successfully deployed to production + if (API!.EndpointConfiguration.BeatmapSubmissionServiceUrl == null) + throw new NotSupportedException("Beatmap submission not supported in this configuration!"); + + return $@"{API!.EndpointConfiguration.BeatmapSubmissionServiceUrl!}/beatmapsets/{BeatmapSetID}"; + } + } + + protected override string Target => throw new NotSupportedException(); + + public uint BeatmapSetID { get; } + public Dictionary FilesChanged { get; } = new Dictionary(); + public HashSet FilesDeleted { get; } = new HashSet(); + + public PatchBeatmapPackageRequest(uint beatmapSetId) + { + BeatmapSetID = beatmapSetId; + } + + protected override WebRequest CreateWebRequest() + { + var request = base.CreateWebRequest(); + request.Method = HttpMethod.Patch; + + foreach ((string filename, byte[] content) in FilesChanged) + request.AddFile(@"filesChanged", content, filename); + + foreach (string filename in FilesDeleted) + request.AddParameter(@"filesDeleted", filename, RequestParameterType.Form); + + request.Timeout = 60_000; + return request; + } + } +} diff --git a/osu.Game/Online/API/Requests/PutBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/PutBeatmapSetRequest.cs new file mode 100644 index 0000000000..03b8397681 --- /dev/null +++ b/osu.Game/Online/API/Requests/PutBeatmapSetRequest.cs @@ -0,0 +1,82 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using osu.Framework.IO.Network; +using osu.Framework.Localisation; +using osu.Game.Localisation; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class PutBeatmapSetRequest : APIRequest + { + protected override string Uri + { + get + { + // can be removed once the service has been successfully deployed to production + if (API!.EndpointConfiguration.BeatmapSubmissionServiceUrl == null) + throw new NotSupportedException("Beatmap submission not supported in this configuration!"); + + return $@"{API!.EndpointConfiguration.BeatmapSubmissionServiceUrl}/beatmapsets"; + } + } + + protected override string Target => throw new NotSupportedException(); + + [JsonProperty("beatmapset_id")] + public uint? BeatmapSetID { get; init; } + + [JsonProperty("beatmaps_to_create")] + public uint BeatmapsToCreate { get; init; } + + [JsonProperty("beatmaps_to_keep")] + public uint[] BeatmapsToKeep { get; init; } = []; + + [JsonProperty("target")] + public BeatmapSubmissionTarget SubmissionTarget { get; init; } + + private PutBeatmapSetRequest() + { + } + + public static PutBeatmapSetRequest CreateNew(uint beatmapCount, BeatmapSubmissionTarget target) => new PutBeatmapSetRequest + { + BeatmapsToCreate = beatmapCount, + SubmissionTarget = target, + }; + + public static PutBeatmapSetRequest UpdateExisting(uint beatmapSetId, IEnumerable beatmapsToKeep, uint beatmapsToCreate, BeatmapSubmissionTarget target) => new PutBeatmapSetRequest + { + BeatmapSetID = beatmapSetId, + BeatmapsToKeep = beatmapsToKeep.ToArray(), + BeatmapsToCreate = beatmapsToCreate, + SubmissionTarget = target, + }; + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.Method = HttpMethod.Put; + req.ContentType = @"application/json"; + req.AddRaw(JsonConvert.SerializeObject(this)); + return req; + } + } + + [JsonConverter(typeof(StringEnumConverter))] + public enum BeatmapSubmissionTarget + { + [LocalisableDescription(typeof(BeatmapSubmissionStrings), nameof(BeatmapSubmissionStrings.BeatmapSubmissionTargetWIP))] + WIP, + + [LocalisableDescription(typeof(BeatmapSubmissionStrings), nameof(BeatmapSubmissionStrings.BeatmapSubmissionTargetPending))] + Pending, + } +} diff --git a/osu.Game/Online/API/Requests/ReplaceBeatmapPackageRequest.cs b/osu.Game/Online/API/Requests/ReplaceBeatmapPackageRequest.cs new file mode 100644 index 0000000000..c9dd12d61e --- /dev/null +++ b/osu.Game/Online/API/Requests/ReplaceBeatmapPackageRequest.cs @@ -0,0 +1,45 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Net.Http; +using osu.Framework.IO.Network; + +namespace osu.Game.Online.API.Requests +{ + public class ReplaceBeatmapPackageRequest : APIUploadRequest + { + protected override string Uri + { + get + { + // can be removed once the service has been successfully deployed to production + if (API!.EndpointConfiguration.BeatmapSubmissionServiceUrl == null) + throw new NotSupportedException("Beatmap submission not supported in this configuration!"); + + return $@"{API!.EndpointConfiguration.BeatmapSubmissionServiceUrl}/beatmapsets/{BeatmapSetID}"; + } + } + + protected override string Target => throw new NotSupportedException(); + + public uint BeatmapSetID { get; } + + private readonly byte[] oszPackage; + + public ReplaceBeatmapPackageRequest(uint beatmapSetID, byte[] oszPackage) + { + this.oszPackage = oszPackage; + BeatmapSetID = beatmapSetID; + } + + protected override WebRequest CreateWebRequest() + { + var request = base.CreateWebRequest(); + request.AddFile(@"beatmapArchive", oszPackage); + request.Method = HttpMethod.Put; + request.Timeout = 60_000; + return request; + } + } +} diff --git a/osu.Game/Online/API/Requests/Responses/PutBeatmapSetResponse.cs b/osu.Game/Online/API/Requests/Responses/PutBeatmapSetResponse.cs new file mode 100644 index 0000000000..e3ec617039 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/PutBeatmapSetResponse.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class PutBeatmapSetResponse + { + [JsonProperty("beatmapset_id")] + public uint BeatmapSetId { get; set; } + + [JsonProperty("beatmap_ids")] + public ICollection BeatmapIds { get; set; } = Array.Empty(); + + [JsonProperty("files")] + public ICollection Files { get; set; } = Array.Empty(); + } + + public struct BeatmapSetFile + { + [JsonProperty("filename")] + public string Filename { get; set; } + + [JsonProperty("sha2_hash")] + public string SHA2Hash { get; set; } + } +}