From 04c07403069133bcf8455f67c22de6f9ea8e5482 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sun, 5 Jul 2026 00:48:11 -0400 Subject: [PATCH] Reorganize quarantine zone --- .../RedumpOrg/UrlBuilderTests.cs | 6 +- SabreTools.RedumpLib/RedumpOrg/Client.cs | 7 + .../Converters/LanguageSelectionConverter.cs | 1 + .../Converters/PhysicalSystemConverter.cs | 1 + .../RedumpOrg/Converters/RegionConverter.cs | 1 + .../RedumpOrg/{ => Data}/Constants.cs | 3 +- .../RedumpOrg/{ => Data}/Enumerations.cs | 2 +- .../RedumpOrg/{ => Data}/Extensions.cs | 7 +- .../Sections/CommonDiscInfoSection.cs | 6 +- .../Sections/CopyProtectionSection.cs | 2 +- .../Sections/DumpersAndStatusSection.cs | 2 +- .../{ => Data}/Sections/DumpingInfoSection.cs | 2 +- .../{ => Data}/Sections/EDCSection.cs | 2 +- .../{ => Data}/Sections/ExtrasSection.cs | 2 +- .../ParentCloneRelationshipSection.cs | 2 +- .../Sections/SizeAndChecksumsSection.cs | 2 +- .../Sections/TracksAndWriteOffsetsSection.cs | 2 +- .../Sections/VersionAndEditionsSection.cs | 2 +- .../RedumpOrg/{ => Data}/SubmissionInfo.cs | 4 +- SabreTools.RedumpLib/RedumpOrg/Discs.cs | 4 + SabreTools.RedumpLib/RedumpOrg/Packs.cs | 3 +- .../RedumpOrg/Tools/Builder.cs | 471 ++++++++++++++++++ .../RedumpOrg/{ => Tools}/Formatter.cs | 9 +- .../RedumpOrg/{ => Tools}/Validator.cs | 4 +- SabreTools.RedumpLib/RedumpOrg/UrlBuilder.cs | 6 + SabreTools.RedumpLib/Tools/Builder.cs | 367 -------------- 26 files changed, 526 insertions(+), 394 deletions(-) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Constants.cs (99%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Enumerations.cs (99%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Extensions.cs (99%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Sections/CommonDiscInfoSection.cs (97%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Sections/CopyProtectionSection.cs (97%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Sections/DumpersAndStatusSection.cs (94%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Sections/DumpingInfoSection.cs (97%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Sections/EDCSection.cs (91%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Sections/ExtrasSection.cs (96%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Sections/ParentCloneRelationshipSection.cs (93%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Sections/SizeAndChecksumsSection.cs (95%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Sections/TracksAndWriteOffsetsSection.cs (96%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/Sections/VersionAndEditionsSection.cs (95%) rename SabreTools.RedumpLib/RedumpOrg/{ => Data}/SubmissionInfo.cs (98%) create mode 100644 SabreTools.RedumpLib/RedumpOrg/Tools/Builder.cs rename SabreTools.RedumpLib/RedumpOrg/{ => Tools}/Formatter.cs (98%) rename SabreTools.RedumpLib/RedumpOrg/{ => Tools}/Validator.cs (96%) diff --git a/SabreTools.RedumpLib.Test/RedumpOrg/UrlBuilderTests.cs b/SabreTools.RedumpLib.Test/RedumpOrg/UrlBuilderTests.cs index 864de34..873c628 100644 --- a/SabreTools.RedumpLib.Test/RedumpOrg/UrlBuilderTests.cs +++ b/SabreTools.RedumpLib.Test/RedumpOrg/UrlBuilderTests.cs @@ -2,9 +2,9 @@ using System; using SabreTools.RedumpLib.Data; using SabreTools.RedumpLib.RedumpOrg; using Xunit; -using DiscSubpath = SabreTools.RedumpLib.RedumpOrg.DiscSubpath; -using PackType = SabreTools.RedumpLib.RedumpOrg.PackType; -using PhysicalSystem = SabreTools.RedumpLib.RedumpOrg.PhysicalSystem; +using DiscSubpath = SabreTools.RedumpLib.RedumpOrg.Data.DiscSubpath; +using PackType = SabreTools.RedumpLib.RedumpOrg.Data.PackType; +using PhysicalSystem = SabreTools.RedumpLib.RedumpOrg.Data.PhysicalSystem; namespace SabreTools.RedumpLib.Test.RedumpOrg { diff --git a/SabreTools.RedumpLib/RedumpOrg/Client.cs b/SabreTools.RedumpLib/RedumpOrg/Client.cs index 0444f0b..fcdb8f0 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Client.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Client.cs @@ -10,7 +10,14 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using SabreTools.RedumpLib.Data; +using SabreTools.RedumpLib.RedumpOrg.Data; using SabreTools.RedumpLib.Web; +using Constants = SabreTools.RedumpLib.RedumpOrg.Data.Constants; +using DiscSubpath = SabreTools.RedumpLib.RedumpOrg.Data.DiscSubpath; +using Language = SabreTools.RedumpLib.RedumpOrg.Data.Language; +using PackType = SabreTools.RedumpLib.RedumpOrg.Data.PackType; +using PhysicalSystem = SabreTools.RedumpLib.RedumpOrg.Data.PhysicalSystem; +using Region = SabreTools.RedumpLib.RedumpOrg.Data.Region; namespace SabreTools.RedumpLib.RedumpOrg { diff --git a/SabreTools.RedumpLib/RedumpOrg/Converters/LanguageSelectionConverter.cs b/SabreTools.RedumpLib/RedumpOrg/Converters/LanguageSelectionConverter.cs index df0b1fc..73190b5 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Converters/LanguageSelectionConverter.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Converters/LanguageSelectionConverter.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using SabreTools.RedumpLib.RedumpOrg.Data; namespace SabreTools.RedumpLib.RedumpOrg.Converters { diff --git a/SabreTools.RedumpLib/RedumpOrg/Converters/PhysicalSystemConverter.cs b/SabreTools.RedumpLib/RedumpOrg/Converters/PhysicalSystemConverter.cs index 74ba073..ad34fb0 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Converters/PhysicalSystemConverter.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Converters/PhysicalSystemConverter.cs @@ -1,6 +1,7 @@ using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using SabreTools.RedumpLib.RedumpOrg.Data; namespace SabreTools.RedumpLib.RedumpOrg.Converters { diff --git a/SabreTools.RedumpLib/RedumpOrg/Converters/RegionConverter.cs b/SabreTools.RedumpLib/RedumpOrg/Converters/RegionConverter.cs index 21c5d11..774aa1b 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Converters/RegionConverter.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Converters/RegionConverter.cs @@ -1,6 +1,7 @@ using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using SabreTools.RedumpLib.RedumpOrg.Data; namespace SabreTools.RedumpLib.RedumpOrg.Converters { diff --git a/SabreTools.RedumpLib/RedumpOrg/Constants.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Constants.cs similarity index 99% rename from SabreTools.RedumpLib/RedumpOrg/Constants.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Constants.cs index 7802bb9..487f125 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Constants.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Constants.cs @@ -1,7 +1,6 @@ using System.Text.RegularExpressions; -using SabreTools.RedumpLib.Data; -namespace SabreTools.RedumpLib.RedumpOrg +namespace SabreTools.RedumpLib.RedumpOrg.Data { public static class Constants { diff --git a/SabreTools.RedumpLib/RedumpOrg/Enumerations.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Enumerations.cs similarity index 99% rename from SabreTools.RedumpLib/RedumpOrg/Enumerations.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Enumerations.cs index cdfbf32..79f1cc4 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Enumerations.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Enumerations.cs @@ -3,7 +3,7 @@ using SabreTools.RedumpLib.RedumpOrg.Attributes; using HumanReadableAttribute = SabreTools.RedumpLib.Attributes.HumanReadableAttribute; using LanguageCodeAttribute = SabreTools.RedumpLib.Attributes.LanguageCodeAttribute; -namespace SabreTools.RedumpLib.RedumpOrg +namespace SabreTools.RedumpLib.RedumpOrg.Data { /// /// List of all disc subpaths diff --git a/SabreTools.RedumpLib/RedumpOrg/Extensions.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Extensions.cs similarity index 99% rename from SabreTools.RedumpLib/RedumpOrg/Extensions.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Extensions.cs index 33d6261..a73712a 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Extensions.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Extensions.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; using SabreTools.RedumpLib.Attributes; -using SabreTools.RedumpLib.Data; +using MediaType = SabreTools.RedumpLib.Data.MediaType; using SystemAttribute = SabreTools.RedumpLib.RedumpOrg.Attributes.SystemAttribute; +using SystemCategory = SabreTools.RedumpLib.Data.SystemCategory; -namespace SabreTools.RedumpLib.RedumpOrg +namespace SabreTools.RedumpLib.RedumpOrg.Data { /// /// Information pertaining to Redump systems @@ -42,7 +43,7 @@ namespace SabreTools.RedumpLib.RedumpOrg case MediaType.BD100: case MediaType.BD128: // Extract the size from the hashes - long size = Data.Extensions.ExtractSizeFromHashData(info.TracksAndWriteOffsets.ClrMameProData); + long size = RedumpLib.Data.Extensions.ExtractSizeFromHashData(info.TracksAndWriteOffsets.ClrMameProData); if (info.SizeAndChecksums.Layerbreak3 != default) info.CommonDiscInfo.Media = MediaType.BD128; diff --git a/SabreTools.RedumpLib/RedumpOrg/Sections/CommonDiscInfoSection.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/CommonDiscInfoSection.cs similarity index 97% rename from SabreTools.RedumpLib/RedumpOrg/Sections/CommonDiscInfoSection.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Sections/CommonDiscInfoSection.cs index 75a9fb6..a50e407 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Sections/CommonDiscInfoSection.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/CommonDiscInfoSection.cs @@ -2,9 +2,11 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; using SabreTools.RedumpLib.Converters; -using SabreTools.RedumpLib.Data; +using DiscCategory = SabreTools.RedumpLib.Data.DiscCategory; +using MediaType = SabreTools.RedumpLib.Data.MediaType; +using SiteCode = SabreTools.RedumpLib.Data.SiteCode; -namespace SabreTools.RedumpLib.RedumpOrg.Sections +namespace SabreTools.RedumpLib.RedumpOrg.Data.Sections { /// /// Common disc info section of New Disc Form diff --git a/SabreTools.RedumpLib/RedumpOrg/Sections/CopyProtectionSection.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/CopyProtectionSection.cs similarity index 97% rename from SabreTools.RedumpLib/RedumpOrg/Sections/CopyProtectionSection.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Sections/CopyProtectionSection.cs index 65e8a4b..a699a02 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Sections/CopyProtectionSection.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/CopyProtectionSection.cs @@ -4,7 +4,7 @@ using Newtonsoft.Json; using SabreTools.RedumpLib.Converters; using SabreTools.RedumpLib.Data; -namespace SabreTools.RedumpLib.RedumpOrg.Sections +namespace SabreTools.RedumpLib.RedumpOrg.Data.Sections { /// /// Copy protection section of New Disc form diff --git a/SabreTools.RedumpLib/RedumpOrg/Sections/DumpersAndStatusSection.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/DumpersAndStatusSection.cs similarity index 94% rename from SabreTools.RedumpLib/RedumpOrg/Sections/DumpersAndStatusSection.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Sections/DumpersAndStatusSection.cs index 3ecbd12..ba4dadf 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Sections/DumpersAndStatusSection.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/DumpersAndStatusSection.cs @@ -2,7 +2,7 @@ using System; using Newtonsoft.Json; using SabreTools.RedumpLib.Data; -namespace SabreTools.RedumpLib.RedumpOrg.Sections +namespace SabreTools.RedumpLib.RedumpOrg.Data.Sections { /// /// Dumpers and status section of New Disc form (Moderator only) diff --git a/SabreTools.RedumpLib/RedumpOrg/Sections/DumpingInfoSection.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/DumpingInfoSection.cs similarity index 97% rename from SabreTools.RedumpLib/RedumpOrg/Sections/DumpingInfoSection.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Sections/DumpingInfoSection.cs index 95047a1..412d7dd 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Sections/DumpingInfoSection.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/DumpingInfoSection.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; -namespace SabreTools.RedumpLib.RedumpOrg.Sections +namespace SabreTools.RedumpLib.RedumpOrg.Data.Sections { /// /// Dumping info section for moderation diff --git a/SabreTools.RedumpLib/RedumpOrg/Sections/EDCSection.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/EDCSection.cs similarity index 91% rename from SabreTools.RedumpLib/RedumpOrg/Sections/EDCSection.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Sections/EDCSection.cs index 6d1ddfe..ad59ff3 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Sections/EDCSection.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/EDCSection.cs @@ -3,7 +3,7 @@ using Newtonsoft.Json; using SabreTools.RedumpLib.Converters; using SabreTools.RedumpLib.Data; -namespace SabreTools.RedumpLib.RedumpOrg.Sections +namespace SabreTools.RedumpLib.RedumpOrg.Data.Sections { /// /// EDC section of New Disc form (PSX only) diff --git a/SabreTools.RedumpLib/RedumpOrg/Sections/ExtrasSection.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/ExtrasSection.cs similarity index 96% rename from SabreTools.RedumpLib/RedumpOrg/Sections/ExtrasSection.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Sections/ExtrasSection.cs index 8f9c0d3..6706923 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Sections/ExtrasSection.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/ExtrasSection.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; -namespace SabreTools.RedumpLib.RedumpOrg.Sections +namespace SabreTools.RedumpLib.RedumpOrg.Data.Sections { /// /// Extras section of New Disc form diff --git a/SabreTools.RedumpLib/RedumpOrg/Sections/ParentCloneRelationshipSection.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/ParentCloneRelationshipSection.cs similarity index 93% rename from SabreTools.RedumpLib/RedumpOrg/Sections/ParentCloneRelationshipSection.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Sections/ParentCloneRelationshipSection.cs index 1eae56f..6f27fc2 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Sections/ParentCloneRelationshipSection.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/ParentCloneRelationshipSection.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; -namespace SabreTools.RedumpLib.RedumpOrg.Sections +namespace SabreTools.RedumpLib.RedumpOrg.Data.Sections { /// /// Parent/Clone relationship section of New Disc form diff --git a/SabreTools.RedumpLib/RedumpOrg/Sections/SizeAndChecksumsSection.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/SizeAndChecksumsSection.cs similarity index 95% rename from SabreTools.RedumpLib/RedumpOrg/Sections/SizeAndChecksumsSection.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Sections/SizeAndChecksumsSection.cs index 9f2bb0f..d121ca6 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Sections/SizeAndChecksumsSection.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/SizeAndChecksumsSection.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; -namespace SabreTools.RedumpLib.RedumpOrg.Sections +namespace SabreTools.RedumpLib.RedumpOrg.Data.Sections { /// /// Size & checksums section of New Disc form (DVD/BD/UMD-based) diff --git a/SabreTools.RedumpLib/RedumpOrg/Sections/TracksAndWriteOffsetsSection.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/TracksAndWriteOffsetsSection.cs similarity index 96% rename from SabreTools.RedumpLib/RedumpOrg/Sections/TracksAndWriteOffsetsSection.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Sections/TracksAndWriteOffsetsSection.cs index 036cab0..c84c257 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Sections/TracksAndWriteOffsetsSection.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/TracksAndWriteOffsetsSection.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; -namespace SabreTools.RedumpLib.RedumpOrg.Sections +namespace SabreTools.RedumpLib.RedumpOrg.Data.Sections { /// /// Tracks and write offsets section of New Disc form (CD/GD-based) diff --git a/SabreTools.RedumpLib/RedumpOrg/Sections/VersionAndEditionsSection.cs b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/VersionAndEditionsSection.cs similarity index 95% rename from SabreTools.RedumpLib/RedumpOrg/Sections/VersionAndEditionsSection.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/Sections/VersionAndEditionsSection.cs index b4ab595..f13bd60 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Sections/VersionAndEditionsSection.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/Sections/VersionAndEditionsSection.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; -namespace SabreTools.RedumpLib.RedumpOrg.Sections +namespace SabreTools.RedumpLib.RedumpOrg.Data.Sections { /// /// Version and editions section of New Disc form diff --git a/SabreTools.RedumpLib/RedumpOrg/SubmissionInfo.cs b/SabreTools.RedumpLib/RedumpOrg/Data/SubmissionInfo.cs similarity index 98% rename from SabreTools.RedumpLib/RedumpOrg/SubmissionInfo.cs rename to SabreTools.RedumpLib/RedumpOrg/Data/SubmissionInfo.cs index 275b97f..f1dd1fc 100644 --- a/SabreTools.RedumpLib/RedumpOrg/SubmissionInfo.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Data/SubmissionInfo.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; -using SabreTools.RedumpLib.RedumpOrg.Sections; +using SabreTools.RedumpLib.RedumpOrg.Data.Sections; -namespace SabreTools.RedumpLib.RedumpOrg +namespace SabreTools.RedumpLib.RedumpOrg.Data { /// /// redump.org submission page information diff --git a/SabreTools.RedumpLib/RedumpOrg/Discs.cs b/SabreTools.RedumpLib/RedumpOrg/Discs.cs index 652b7a3..83c1a6c 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Discs.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Discs.cs @@ -3,6 +3,10 @@ using System.Collections.Generic; using System.Threading.Tasks; using SabreTools.RedumpLib.Data; using SabreTools.RedumpLib.Web; +using DiscSubpath = SabreTools.RedumpLib.RedumpOrg.Data.DiscSubpath; +using Language = SabreTools.RedumpLib.RedumpOrg.Data.Language; +using PhysicalSystem = SabreTools.RedumpLib.RedumpOrg.Data.PhysicalSystem; +using Region = SabreTools.RedumpLib.RedumpOrg.Data.Region; namespace SabreTools.RedumpLib.RedumpOrg { diff --git a/SabreTools.RedumpLib/RedumpOrg/Packs.cs b/SabreTools.RedumpLib/RedumpOrg/Packs.cs index c7b33de..18b9cf3 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Packs.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Packs.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; -using SabreTools.RedumpLib.Data; +using PackType = SabreTools.RedumpLib.RedumpOrg.Data.PackType; +using PhysicalSystem = SabreTools.RedumpLib.RedumpOrg.Data.PhysicalSystem; namespace SabreTools.RedumpLib.RedumpOrg { diff --git a/SabreTools.RedumpLib/RedumpOrg/Tools/Builder.cs b/SabreTools.RedumpLib/RedumpOrg/Tools/Builder.cs new file mode 100644 index 0000000..a809e00 --- /dev/null +++ b/SabreTools.RedumpLib/RedumpOrg/Tools/Builder.cs @@ -0,0 +1,471 @@ +using System; +using System.Collections.Generic; +#if NET40_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER +using System.Net; +#endif +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using SabreTools.RedumpLib.Data; +using Constants = SabreTools.RedumpLib.RedumpOrg.Data.Constants; +using Language = SabreTools.RedumpLib.RedumpOrg.Data.Language; +using SubmissionInfo = SabreTools.RedumpLib.RedumpOrg.Data.SubmissionInfo; + +namespace SabreTools.RedumpLib.RedumpOrg.Tools +{ + public static class Builder + { + #region Creation + + /// + /// Fill out an existing SubmissionInfo object based on a disc page + /// + /// RedumpClient for making the connection + /// Existing SubmissionInfo object to fill + /// Redump disc ID to retrieve + /// True to include all pullable information, false to do bare minimum + public static async Task FillFromId(Client client, SubmissionInfo info, int id, bool includeAllData) + { + var discData = await client.DownloadSingleDiscPage(id); + if (string.IsNullOrEmpty(discData)) + return false; + + // Title, Disc Number/Letter, Disc Title + var match = Constants.TitleRegex.Match(discData); + if (match.Success) + { + string? title = WebUtility.HtmlDecode(match.Groups[1].Value); + + // If we have parenthesis, title is everything before the first one + int firstParenLocation = title?.IndexOf(" (") ?? -1; + if (title is not null && firstParenLocation >= 0) + { +#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER + info.CommonDiscInfo.Title = title[..firstParenLocation]; +#else + info.CommonDiscInfo.Title = title.Substring(0, firstParenLocation); +#endif + var submatches = Constants.DiscNumberLetterRegex.Matches(title); + foreach (Match? submatch in submatches) + { + if (submatch is null) + continue; + + var submatchValue = submatch.Groups[1].Value; + + // Disc number or letter + if (submatchValue.StartsWith("Disc")) +#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER + info.CommonDiscInfo.DiscNumberLetter = submatchValue["Disc ".Length..]; +#else + info.CommonDiscInfo.DiscNumberLetter = submatchValue.Remove(0, "Disc ".Length); +#endif + + // Issue number + else if (ulong.TryParse(submatchValue, out _)) + info.CommonDiscInfo.Title += $" ({submatchValue})"; + + // Disc title + else + info.CommonDiscInfo.DiscTitle = submatchValue; + } + } + // Otherwise, leave the title as-is + else + { + info.CommonDiscInfo.Title = title; + } + } + + // Foreign Title + match = Constants.ForeignTitleRegex.Match(discData); + if (match.Success) + info.CommonDiscInfo.ForeignTitleNonLatin = WebUtility.HtmlDecode(match.Groups[1].Value); + + // Category + match = Constants.CategoryRegex.Match(discData); + if (match.Success) + info.CommonDiscInfo.Category = match.Groups[1].Value.ToDiscCategory(); + else + info.CommonDiscInfo.Category = DiscCategory.Games; + + // Region + if (info.CommonDiscInfo.Region is null) + { + match = Constants.RegionRegex.Match(discData); + if (match.Success) + info.CommonDiscInfo.Region = Data.Extensions.ToRegion(match.Groups[1].Value); + } + + // Languages + var matches = Constants.LanguagesRegex.Matches(discData); + if (matches.Count > 0) + { + var tempLanguages = new List(); + foreach (Match? submatch in matches) + { + if (submatch is null) + continue; + + var language = Data.Extensions.ToLanguage(submatch.Groups[1].Value); + if (language is not null) + tempLanguages.Add(language); + } + + info.CommonDiscInfo.Languages = [.. tempLanguages]; + } + + // Serial + if (includeAllData) + { + // TODO: Re-enable if there's a way of verifying against a disc + //match = Constants.SerialRegex.Match(discData); + //if (match.Success) + // info.CommonDiscInfo.Serial = $"(VERIFY THIS) {WebUtility.HtmlDecode(match.Groups[1].Value)}"; + } + + // Error count + if (string.IsNullOrEmpty(info.CommonDiscInfo.ErrorsCount)) + { + match = Constants.ErrorCountRegex.Match(discData); + if (match.Success) + info.CommonDiscInfo.ErrorsCount = match.Groups[1].Value; + } + + // Version + if (info.VersionAndEditions.Version is null) + { + match = Constants.VersionRegex.Match(discData); + if (match.Success) + info.VersionAndEditions.Version = $"(VERIFY THIS) {WebUtility.HtmlDecode(match.Groups[1].Value)}"; + } + + // Dumpers + matches = Constants.DumpersRegex.Matches(discData); + if (matches.Count > 0) + { + // Start with any currently listed dumpers + var tempDumpers = new List(); + if (info.DumpersAndStatus.Dumpers is not null && info.DumpersAndStatus.Dumpers.Length > 0) + { + foreach (string dumper in info.DumpersAndStatus.Dumpers) + tempDumpers.Add(dumper); + } + + foreach (Match? submatch in matches) + { + if (submatch is null) + continue; + + string? dumper = WebUtility.HtmlDecode(submatch.Groups[1].Value); + if (dumper is not null) + tempDumpers.Add(dumper); + } + + info.DumpersAndStatus.Dumpers = [.. tempDumpers]; + } + + // PS3 DiscKey + if (string.IsNullOrEmpty(info.Extras.DiscKey)) + { + // Validate key is not NULL + match = Constants.PS3DiscKey.Match(discData); + if (match.Success && match.Groups[1].Value != "NULL") + info.Extras.DiscKey = match.Groups[1].Value; + } + + // TODO: Unify handling of fields that can include site codes (Comments/Contents) + + // Comments + if (includeAllData) + { + match = Constants.CommentsRegex.Match(discData); + if (match.Success) + { + // Process the old comments block + string oldComments = info.CommonDiscInfo.Comments + + (string.IsNullOrEmpty(info.CommonDiscInfo.Comments) ? string.Empty : "\n") + + (WebUtility.HtmlDecode(match.Groups[1].Value) ?? string.Empty) + .Replace("\r\n", "\n") + .Replace("
\n", "\n") + .Replace("
", string.Empty) + .Replace("", string.Empty) + .Replace("[+]", string.Empty) + .ReplaceHtmlWithSiteCodes(); + oldComments = Regex.Replace(oldComments, @"
", string.Empty, RegexOptions.Compiled); + + // Create state variables + bool addToLast = false; + SiteCode? lastSiteCode = null; + string newComments = string.Empty; + + // Process the comments block line-by-line + string[] commentsSeparated = oldComments.Split('\n'); + for (int i = 0; i < commentsSeparated.Length; i++) + { + string commentLine = commentsSeparated[i].Trim(); + + // If we have an empty line, we want to treat this as intentional + if (string.IsNullOrEmpty(commentLine)) + { + addToLast = false; + lastSiteCode = null; + newComments += $"{commentLine}\n"; + continue; + } + + // Otherwise, we need to find what tag is in use + bool foundTag = false; + foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode))) + { + // If we have a null site code, just skip + if (siteCode is null) + continue; + + // If the line doesn't contain this tag, just skip + var shortName = siteCode.ShortName(); + if (shortName is null || !commentLine.Contains(shortName)) + continue; + + // Mark as having found a tag + foundTag = true; + + // Cache the current site code + lastSiteCode = siteCode; + + // A subset of tags can be multiline + addToLast = siteCode.IsMultiLine(); + + // Skip certain site codes because of data issues + if (ShouldSkipSiteCode(siteCode)) + continue; + + // If we don't already have this site code, add it to the dictionary + if (!info.CommonDiscInfo.CommentsSpecialFields.ContainsKey(siteCode.Value)) + info.CommonDiscInfo.CommentsSpecialFields[siteCode.Value] = $"(VERIFY THIS) {commentLine.Replace(shortName, string.Empty).Trim()}"; + + // Otherwise, append the value to the existing key + else + info.CommonDiscInfo.CommentsSpecialFields[siteCode.Value] += $", {commentLine.Replace(shortName, string.Empty).Trim()}"; + + break; + } + + // If we didn't find a known tag, just add the line, just in case + if (!foundTag) + { + if (addToLast && lastSiteCode is not null && !ShouldSkipSiteCode(lastSiteCode)) + { + if (!string.IsNullOrEmpty(info.CommonDiscInfo.CommentsSpecialFields![lastSiteCode.Value])) + info.CommonDiscInfo.CommentsSpecialFields[lastSiteCode.Value] += "\n"; + + info.CommonDiscInfo.CommentsSpecialFields[lastSiteCode.Value] += commentLine; + } + else if (!addToLast || lastSiteCode is null) + { + newComments += $"{commentLine}\n"; + } + } + } + + // Set the new comments field + info.CommonDiscInfo.Comments = newComments; + } + } + + // Contents + if (includeAllData) + { + match = Constants.ContentsRegex.Match(discData); + if (match.Success) + { + // Process the old contents block + string oldContents = info.CommonDiscInfo.Contents + + (string.IsNullOrEmpty(info.CommonDiscInfo.Contents) ? string.Empty : "\n") + + (WebUtility.HtmlDecode(match.Groups[1].Value) ?? string.Empty) + .Replace("\r\n", "\n") + .Replace("
\n", "\n") + .Replace("
", string.Empty) + .Replace("
", string.Empty) + .Replace("[+]", string.Empty) + .ReplaceHtmlWithSiteCodes(); + oldContents = Regex.Replace(oldContents, @"
", string.Empty, RegexOptions.Compiled); + + // Create state variables + bool addToLast = false; + SiteCode? lastSiteCode = null; + string newContents = string.Empty; + + // Process the contents block line-by-line + string[] contentsSeparated = oldContents.Split('\n'); + for (int i = 0; i < contentsSeparated.Length; i++) + { + string contentLine = contentsSeparated[i].Trim(); + + // If we have an empty line, we want to treat this as intentional + if (string.IsNullOrEmpty(contentLine)) + { + addToLast = false; + lastSiteCode = null; + newContents += $"{contentLine}\n"; + continue; + } + + // Otherwise, we need to find what tag is in use + bool foundTag = false; + foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode))) + { + // If we have a null site code, just skip + if (siteCode is null) + continue; + + // If the line doesn't contain this tag, just skip + var shortName = siteCode.ShortName(); + if (shortName is null || !contentLine.Contains(shortName)) + continue; + + // Cache the current site code + lastSiteCode = siteCode; + + // If we don't already have this site code, add it to the dictionary + if (!info.CommonDiscInfo.ContentsSpecialFields.ContainsKey(siteCode.Value)) + info.CommonDiscInfo.ContentsSpecialFields[siteCode.Value] = $"(VERIFY THIS) {contentLine.Replace(shortName, string.Empty).Trim()}"; + + // A subset of tags can be multiline + addToLast = siteCode.IsMultiLine(); + + // Mark as having found a tag + foundTag = true; + break; + } + + // If we didn't find a known tag, just add the line, just in case + if (!foundTag) + { + if (addToLast && lastSiteCode is not null && !ShouldSkipSiteCode(lastSiteCode)) + { + if (!string.IsNullOrEmpty(info.CommonDiscInfo.ContentsSpecialFields![lastSiteCode.Value])) + info.CommonDiscInfo.ContentsSpecialFields[lastSiteCode.Value] += "\n"; + + info.CommonDiscInfo.ContentsSpecialFields[lastSiteCode.Value] += contentLine; + } + else if (!addToLast || lastSiteCode is null) + { + newContents += $"{contentLine}\n"; + } + } + } + + // Set the new contents field + info.CommonDiscInfo.Contents = newContents; + } + } + + // Added + match = Constants.AddedRegex.Match(discData); + if (match.Success) + { + if (DateTime.TryParse(match.Groups[1].Value, out DateTime added)) + info.Added = added; + else + info.Added = null; + } + + // Last Modified + match = Constants.LastModifiedRegex.Match(discData); + if (match.Success) + { + if (DateTime.TryParse(match.Groups[1].Value, out DateTime lastModified)) + info.LastModified = lastModified; + else + info.LastModified = null; + } + + return true; + } + + /// + /// Determine if a site code should be skipped on pulling + /// + private static bool ShouldSkipSiteCode(SiteCode? siteCode) + { +#pragma warning disable IDE0072 + return siteCode switch + { + // Multiple + SiteCode.HighSierraVolumeDescriptor + or SiteCode.InternalSerialName + or SiteCode.Multisession + or SiteCode.VolumeLabel => true, + + // Audio CD + SiteCode.RingNonZeroDataStart + or SiteCode.RingPerfectAudioOffset + or SiteCode.UniversalHash => true, + + // Microsoft Xbox and Xbox 360 + SiteCode.DMIHash + or SiteCode.PFIHash + or SiteCode.SSHash + or SiteCode.SSVersion + or SiteCode.XMID + or SiteCode.XeMID => true, + + // Microsoft Xbox One and Series X/S + SiteCode.Filename => true, + SiteCode.TitleID => true, + + // Nintendo Gamecube + SiteCode.InternalName => true, + + // Protection + SiteCode.Protection => true, + + _ => false, + }; +#pragma warning restore IDE0072 + } + + #endregion + + #region Helpers + + /// + /// Process a text block and replace with internal identifiers + /// + /// Text block to process + /// Processed text block, if possible + internal static string ReplaceHtmlWithSiteCodes(this string text) + { + // Empty strings are ignored + if (text.Length == 0) + return text; + + foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode))) + { + var longname = siteCode.LongName(); + if (!string.IsNullOrEmpty(longname)) + text = text.Replace(longname, siteCode.ShortName()); + } + + // For some outdated tags, we need to use alternate names + text = text.Replace("Demos:", ((SiteCode?)SiteCode.PlayableDemos).ShortName()); + text = text.Replace("Disney ID:", ((SiteCode?)SiteCode.DisneyInteractiveID).ShortName()); + text = text.Replace("DMI:", ((SiteCode?)SiteCode.DMIHash).ShortName()); + text = text.Replace("LucasArts ID:", ((SiteCode?)SiteCode.LucasArtsID).ShortName()); + text = text.Replace("PFI:", ((SiteCode?)SiteCode.PFIHash).ShortName()); + text = text.Replace("SS:", ((SiteCode?)SiteCode.SSHash).ShortName()); + text = text.Replace("SSv1:", ((SiteCode?)SiteCode.SSHash).ShortName()); + text = text.Replace("SSv1:", ((SiteCode?)SiteCode.SSHash).ShortName()); + text = text.Replace("SSv2:", ((SiteCode?)SiteCode.SSHash).ShortName()); + text = text.Replace("SSv2:", ((SiteCode?)SiteCode.SSHash).ShortName()); + text = text.Replace("SS version:", ((SiteCode?)SiteCode.SSVersion).ShortName()); + text = text.Replace("Universal Hash (SHA-1):", ((SiteCode?)SiteCode.UniversalHash).ShortName()); + text = text.Replace("XeMID:", ((SiteCode?)SiteCode.XeMID).ShortName()); + text = text.Replace("XMID:", ((SiteCode?)SiteCode.XMID).ShortName()); + + return text; + } + + #endregion + } +} diff --git a/SabreTools.RedumpLib/RedumpOrg/Formatter.cs b/SabreTools.RedumpLib/RedumpOrg/Tools/Formatter.cs similarity index 98% rename from SabreTools.RedumpLib/RedumpOrg/Formatter.cs rename to SabreTools.RedumpLib/RedumpOrg/Tools/Formatter.cs index ee8c660..7daadcc 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Formatter.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Tools/Formatter.cs @@ -3,9 +3,12 @@ using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using SabreTools.RedumpLib.Data; -using SabreTools.RedumpLib.RedumpOrg.Sections; +using SabreTools.RedumpLib.RedumpOrg.Data; +using SabreTools.RedumpLib.RedumpOrg.Data.Sections; +using PhysicalSystem = SabreTools.RedumpLib.RedumpOrg.Data.PhysicalSystem; +using SubmissionInfo = SabreTools.RedumpLib.RedumpOrg.Data.SubmissionInfo; -namespace SabreTools.RedumpLib.RedumpOrg +namespace SabreTools.RedumpLib.RedumpOrg.Tools { public static class Formatter { @@ -273,7 +276,7 @@ namespace SabreTools.RedumpLib.RedumpOrg List? partiallyMatchedIDs) { // Extract the size from the hashes - long size = Data.Extensions.ExtractSizeFromHashData(tawo?.ClrMameProData); + long size = RedumpLib.Data.Extensions.ExtractSizeFromHashData(tawo?.ClrMameProData); output.AppendLine("Common Disc Info:"); diff --git a/SabreTools.RedumpLib/RedumpOrg/Validator.cs b/SabreTools.RedumpLib/RedumpOrg/Tools/Validator.cs similarity index 96% rename from SabreTools.RedumpLib/RedumpOrg/Validator.cs rename to SabreTools.RedumpLib/RedumpOrg/Tools/Validator.cs index dfdc740..12ae3aa 100644 --- a/SabreTools.RedumpLib/RedumpOrg/Validator.cs +++ b/SabreTools.RedumpLib/RedumpOrg/Tools/Validator.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; using System.Threading.Tasks; using SabreTools.RedumpLib.Data; +using Constants = SabreTools.RedumpLib.RedumpOrg.Data.Constants; +using SubmissionInfo = SabreTools.RedumpLib.RedumpOrg.Data.SubmissionInfo; -namespace SabreTools.RedumpLib.RedumpOrg +namespace SabreTools.RedumpLib.RedumpOrg.Tools { public static class Validator { diff --git a/SabreTools.RedumpLib/RedumpOrg/UrlBuilder.cs b/SabreTools.RedumpLib/RedumpOrg/UrlBuilder.cs index d0ad14b..e0697e8 100644 --- a/SabreTools.RedumpLib/RedumpOrg/UrlBuilder.cs +++ b/SabreTools.RedumpLib/RedumpOrg/UrlBuilder.cs @@ -1,6 +1,12 @@ using System; using System.Text; using SabreTools.RedumpLib.Data; +using SabreTools.RedumpLib.RedumpOrg.Data; +using DiscSubpath = SabreTools.RedumpLib.RedumpOrg.Data.DiscSubpath; +using Language = SabreTools.RedumpLib.RedumpOrg.Data.Language; +using PackType = SabreTools.RedumpLib.RedumpOrg.Data.PackType; +using PhysicalSystem = SabreTools.RedumpLib.RedumpOrg.Data.PhysicalSystem; +using Region = SabreTools.RedumpLib.RedumpOrg.Data.Region; // TODO: Errors should validate number or number range (# or #-#) diff --git a/SabreTools.RedumpLib/Tools/Builder.cs b/SabreTools.RedumpLib/Tools/Builder.cs index 995dff7..2cff22f 100644 --- a/SabreTools.RedumpLib/Tools/Builder.cs +++ b/SabreTools.RedumpLib/Tools/Builder.cs @@ -397,373 +397,6 @@ namespace SabreTools.RedumpLib.Tools return true; } - /// - /// Fill out an existing SubmissionInfo object based on a disc page - /// - /// RedumpClient for making the connection - /// Existing SubmissionInfo object to fill - /// Redump disc ID to retrieve - /// True to include all pullable information, false to do bare minimum - public static async Task FillFromId(RedumpOrg.Client client, RedumpOrg.SubmissionInfo info, int id, bool includeAllData) - { - var discData = await client.DownloadSingleDiscPage(id); - if (string.IsNullOrEmpty(discData)) - return false; - - // Title, Disc Number/Letter, Disc Title - var match = RedumpOrg.Constants.TitleRegex.Match(discData); - if (match.Success) - { - string? title = WebUtility.HtmlDecode(match.Groups[1].Value); - - // If we have parenthesis, title is everything before the first one - int firstParenLocation = title?.IndexOf(" (") ?? -1; - if (title is not null && firstParenLocation >= 0) - { -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER - info.CommonDiscInfo.Title = title[..firstParenLocation]; -#else - info.CommonDiscInfo.Title = title.Substring(0, firstParenLocation); -#endif - var submatches = RedumpOrg.Constants.DiscNumberLetterRegex.Matches(title); - foreach (Match? submatch in submatches) - { - if (submatch is null) - continue; - - var submatchValue = submatch.Groups[1].Value; - - // Disc number or letter - if (submatchValue.StartsWith("Disc")) -#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER - info.CommonDiscInfo.DiscNumberLetter = submatchValue["Disc ".Length..]; -#else - info.CommonDiscInfo.DiscNumberLetter = submatchValue.Remove(0, "Disc ".Length); -#endif - - // Issue number - else if (ulong.TryParse(submatchValue, out _)) - info.CommonDiscInfo.Title += $" ({submatchValue})"; - - // Disc title - else - info.CommonDiscInfo.DiscTitle = submatchValue; - } - } - // Otherwise, leave the title as-is - else - { - info.CommonDiscInfo.Title = title; - } - } - - // Foreign Title - match = RedumpOrg.Constants.ForeignTitleRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.ForeignTitleNonLatin = WebUtility.HtmlDecode(match.Groups[1].Value); - - // Category - match = RedumpOrg.Constants.CategoryRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Category = match.Groups[1].Value.ToDiscCategory(); - else - info.CommonDiscInfo.Category = DiscCategory.Games; - - // Region - if (info.CommonDiscInfo.Region is null) - { - match = RedumpOrg.Constants.RegionRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.Region = RedumpOrg.Extensions.ToRegion(match.Groups[1].Value); - } - - // Languages - var matches = RedumpOrg.Constants.LanguagesRegex.Matches(discData); - if (matches.Count > 0) - { - var tempLanguages = new List(); - foreach (Match? submatch in matches) - { - if (submatch is null) - continue; - - var language = RedumpOrg.Extensions.ToLanguage(submatch.Groups[1].Value); - if (language is not null) - tempLanguages.Add(language); - } - - info.CommonDiscInfo.Languages = [.. tempLanguages]; - } - - // Serial - if (includeAllData) - { - // TODO: Re-enable if there's a way of verifying against a disc - //match = Constants.SerialRegex.Match(discData); - //if (match.Success) - // info.CommonDiscInfo.Serial = $"(VERIFY THIS) {WebUtility.HtmlDecode(match.Groups[1].Value)}"; - } - - // Error count - if (string.IsNullOrEmpty(info.CommonDiscInfo.ErrorsCount)) - { - match = RedumpOrg.Constants.ErrorCountRegex.Match(discData); - if (match.Success) - info.CommonDiscInfo.ErrorsCount = match.Groups[1].Value; - } - - // Version - if (info.VersionAndEditions.Version is null) - { - match = RedumpOrg.Constants.VersionRegex.Match(discData); - if (match.Success) - info.VersionAndEditions.Version = $"(VERIFY THIS) {WebUtility.HtmlDecode(match.Groups[1].Value)}"; - } - - // Dumpers - matches = RedumpOrg.Constants.DumpersRegex.Matches(discData); - if (matches.Count > 0) - { - // Start with any currently listed dumpers - var tempDumpers = new List(); - if (info.DumpersAndStatus.Dumpers is not null && info.DumpersAndStatus.Dumpers.Length > 0) - { - foreach (string dumper in info.DumpersAndStatus.Dumpers) - tempDumpers.Add(dumper); - } - - foreach (Match? submatch in matches) - { - if (submatch is null) - continue; - - string? dumper = WebUtility.HtmlDecode(submatch.Groups[1].Value); - if (dumper is not null) - tempDumpers.Add(dumper); - } - - info.DumpersAndStatus.Dumpers = [.. tempDumpers]; - } - - // PS3 DiscKey - if (string.IsNullOrEmpty(info.Extras.DiscKey)) - { - // Validate key is not NULL - match = RedumpOrg.Constants.PS3DiscKey.Match(discData); - if (match.Success && match.Groups[1].Value != "NULL") - info.Extras.DiscKey = match.Groups[1].Value; - } - - // TODO: Unify handling of fields that can include site codes (Comments/Contents) - - // Comments - if (includeAllData) - { - match = RedumpOrg.Constants.CommentsRegex.Match(discData); - if (match.Success) - { - // Process the old comments block - string oldComments = info.CommonDiscInfo.Comments - + (string.IsNullOrEmpty(info.CommonDiscInfo.Comments) ? string.Empty : "\n") - + (WebUtility.HtmlDecode(match.Groups[1].Value) ?? string.Empty) - .Replace("\r\n", "\n") - .Replace("
\n", "\n") - .Replace("
", string.Empty) - .Replace("
", string.Empty) - .Replace("[+]", string.Empty) - .ReplaceHtmlWithSiteCodes(); - oldComments = Regex.Replace(oldComments, @"
", string.Empty, RegexOptions.Compiled); - - // Create state variables - bool addToLast = false; - SiteCode? lastSiteCode = null; - string newComments = string.Empty; - - // Process the comments block line-by-line - string[] commentsSeparated = oldComments.Split('\n'); - for (int i = 0; i < commentsSeparated.Length; i++) - { - string commentLine = commentsSeparated[i].Trim(); - - // If we have an empty line, we want to treat this as intentional - if (string.IsNullOrEmpty(commentLine)) - { - addToLast = false; - lastSiteCode = null; - newComments += $"{commentLine}\n"; - continue; - } - - // Otherwise, we need to find what tag is in use - bool foundTag = false; - foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode))) - { - // If we have a null site code, just skip - if (siteCode is null) - continue; - - // If the line doesn't contain this tag, just skip - var shortName = siteCode.ShortName(); - if (shortName is null || !commentLine.Contains(shortName)) - continue; - - // Mark as having found a tag - foundTag = true; - - // Cache the current site code - lastSiteCode = siteCode; - - // A subset of tags can be multiline - addToLast = siteCode.IsMultiLine(); - - // Skip certain site codes because of data issues - if (ShouldSkipSiteCode(siteCode)) - continue; - - // If we don't already have this site code, add it to the dictionary - if (!info.CommonDiscInfo.CommentsSpecialFields.ContainsKey(siteCode.Value)) - info.CommonDiscInfo.CommentsSpecialFields[siteCode.Value] = $"(VERIFY THIS) {commentLine.Replace(shortName, string.Empty).Trim()}"; - - // Otherwise, append the value to the existing key - else - info.CommonDiscInfo.CommentsSpecialFields[siteCode.Value] += $", {commentLine.Replace(shortName, string.Empty).Trim()}"; - - break; - } - - // If we didn't find a known tag, just add the line, just in case - if (!foundTag) - { - if (addToLast && lastSiteCode is not null && !ShouldSkipSiteCode(lastSiteCode)) - { - if (!string.IsNullOrEmpty(info.CommonDiscInfo.CommentsSpecialFields![lastSiteCode.Value])) - info.CommonDiscInfo.CommentsSpecialFields[lastSiteCode.Value] += "\n"; - - info.CommonDiscInfo.CommentsSpecialFields[lastSiteCode.Value] += commentLine; - } - else if (!addToLast || lastSiteCode is null) - { - newComments += $"{commentLine}\n"; - } - } - } - - // Set the new comments field - info.CommonDiscInfo.Comments = newComments; - } - } - - // Contents - if (includeAllData) - { - match = RedumpOrg.Constants.ContentsRegex.Match(discData); - if (match.Success) - { - // Process the old contents block - string oldContents = info.CommonDiscInfo.Contents - + (string.IsNullOrEmpty(info.CommonDiscInfo.Contents) ? string.Empty : "\n") - + (WebUtility.HtmlDecode(match.Groups[1].Value) ?? string.Empty) - .Replace("\r\n", "\n") - .Replace("
\n", "\n") - .Replace("
", string.Empty) - .Replace("
", string.Empty) - .Replace("[+]", string.Empty) - .ReplaceHtmlWithSiteCodes(); - oldContents = Regex.Replace(oldContents, @"
", string.Empty, RegexOptions.Compiled); - - // Create state variables - bool addToLast = false; - SiteCode? lastSiteCode = null; - string newContents = string.Empty; - - // Process the contents block line-by-line - string[] contentsSeparated = oldContents.Split('\n'); - for (int i = 0; i < contentsSeparated.Length; i++) - { - string contentLine = contentsSeparated[i].Trim(); - - // If we have an empty line, we want to treat this as intentional - if (string.IsNullOrEmpty(contentLine)) - { - addToLast = false; - lastSiteCode = null; - newContents += $"{contentLine}\n"; - continue; - } - - // Otherwise, we need to find what tag is in use - bool foundTag = false; - foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode))) - { - // If we have a null site code, just skip - if (siteCode is null) - continue; - - // If the line doesn't contain this tag, just skip - var shortName = siteCode.ShortName(); - if (shortName is null || !contentLine.Contains(shortName)) - continue; - - // Cache the current site code - lastSiteCode = siteCode; - - // If we don't already have this site code, add it to the dictionary - if (!info.CommonDiscInfo.ContentsSpecialFields.ContainsKey(siteCode.Value)) - info.CommonDiscInfo.ContentsSpecialFields[siteCode.Value] = $"(VERIFY THIS) {contentLine.Replace(shortName, string.Empty).Trim()}"; - - // A subset of tags can be multiline - addToLast = siteCode.IsMultiLine(); - - // Mark as having found a tag - foundTag = true; - break; - } - - // If we didn't find a known tag, just add the line, just in case - if (!foundTag) - { - if (addToLast && lastSiteCode is not null && !ShouldSkipSiteCode(lastSiteCode)) - { - if (!string.IsNullOrEmpty(info.CommonDiscInfo.ContentsSpecialFields![lastSiteCode.Value])) - info.CommonDiscInfo.ContentsSpecialFields[lastSiteCode.Value] += "\n"; - - info.CommonDiscInfo.ContentsSpecialFields[lastSiteCode.Value] += contentLine; - } - else if (!addToLast || lastSiteCode is null) - { - newContents += $"{contentLine}\n"; - } - } - } - - // Set the new contents field - info.CommonDiscInfo.Contents = newContents; - } - } - - // Added - match = RedumpOrg.Constants.AddedRegex.Match(discData); - if (match.Success) - { - if (DateTime.TryParse(match.Groups[1].Value, out DateTime added)) - info.Added = added; - else - info.Added = null; - } - - // Last Modified - match = RedumpOrg.Constants.LastModifiedRegex.Match(discData); - if (match.Success) - { - if (DateTime.TryParse(match.Groups[1].Value, out DateTime lastModified)) - info.LastModified = lastModified; - else - info.LastModified = null; - } - - return true; - } - /// /// Inject information from a seed SubmissionInfo into the existing one ///