Sync with new queue URL syntax

This commit is contained in:
Matt Nadareski
2026-07-04 18:53:16 -04:00
parent b6252f3a75
commit 7940bf7a79
5 changed files with 298 additions and 7 deletions

View File

@@ -3622,6 +3622,113 @@ namespace SabreTools.RedumpLib.Test.Data
#endregion
#region Submission Type
/// <summary>
/// Check that every SubmissionType has a long name provided
/// </summary>
/// <param name="sortDirection">SubmissionType value to check</param>
/// <param name="expectNull">True to expect a null value, false otherwise</param>
[Theory]
[MemberData(nameof(GenerateSubmissionTypeTestData))]
public void SubmissionType_LongName(SubmissionType? sortDirection, bool expectNull)
{
var actual = sortDirection.LongName();
if (expectNull)
Assert.Null(actual);
else
Assert.NotNull(actual);
}
/// <summary>
/// Check that every SubmissionType has a short name provided
/// </summary>
/// <param name="sortDirection">SubmissionType value to check</param>
/// <param name="expectNull">True to expect a null value, false otherwise</param>
[Theory]
[MemberData(nameof(GenerateSubmissionTypeTestData))]
public void SubmissionType_ShortName(SubmissionType? sortDirection, bool expectNull)
{
var actual = sortDirection.ShortName();
if (expectNull)
Assert.Null(actual);
else
Assert.NotNull(actual);
}
/// <summary>
/// Ensure that every SubmissionType that has a short name that is unique
/// </summary>
[Fact]
public void SubmissionType_ShortName_NoDuplicates()
{
var fullSubmissionTypes = Enum.GetValues<SubmissionType>().Cast<SubmissionType>().ToList();
var filteredSubmissionTypes = new Dictionary<string, SubmissionType?>();
int totalCount = 0;
foreach (SubmissionType? sortDirection in fullSubmissionTypes)
{
var code = sortDirection.ShortName();
if (string.IsNullOrEmpty(code))
continue;
// Throw if the code already exists
if (filteredSubmissionTypes.ContainsKey(code))
throw new DuplicateNameException($"Code {code} already in dictionary");
filteredSubmissionTypes[code] = sortDirection;
totalCount++;
}
Assert.Equal(totalCount, filteredSubmissionTypes.Count);
}
/// <summary>
/// Check that every SubmissionType can be mapped from a string
/// </summary>
/// <param name="sortDirection">SubmissionType value to check</param>
/// <param name="expectNull">True to expect a null value, false otherwise</param>
[Theory]
[MemberData(nameof(GenerateSubmissionTypeTestData))]
public void SubmissionType_ToSubmissionType(SubmissionType? sortDirection, bool expectNull)
{
string? longName = sortDirection.LongName();
string? longNameSpaceless = longName?.Replace(" ", string.Empty);
var actualNormal = longName.ToSubmissionType();
var actualSpaceless = longNameSpaceless.ToSubmissionType();
if (expectNull)
{
Assert.Null(actualNormal);
Assert.Null(actualSpaceless);
}
else
{
Assert.Equal(sortDirection, actualNormal);
Assert.Equal(sortDirection, actualSpaceless);
}
}
/// <summary>
/// Generate a test set of SubmissionType values
/// </summary>
/// <returns>MemberData-compatible list of SubmissionType values</returns>
public static TheoryData<SubmissionType?, bool> GenerateSubmissionTypeTestData()
{
var testData = new TheoryData<SubmissionType?, bool>() { { null, true } };
foreach (SubmissionType? sortDirection in Enum.GetValues<SubmissionType>().Cast<SubmissionType?>())
{
testData.Add(sortDirection, false);
}
return testData;
}
#endregion
#region System Category
/// <summary>

View File

@@ -142,6 +142,7 @@ namespace SabreTools.RedumpLib.Data
DiscSubpath.Cuesheet,
DiscSubpath.Edit,
DiscSubpath.History,
DiscSubpath.SBI,
];
#endregion

View File

@@ -77,7 +77,6 @@ namespace SabreTools.RedumpLib.Data
[HumanReadable(LongName = "MD5", ShortName = "md5")]
MD5,
/// <remarks>Only in redump.org</remarks>
[HumanReadable(LongName = "SBI", ShortName = "sbi")]
SBI,
@@ -3996,6 +3995,21 @@ namespace SabreTools.RedumpLib.Data
Descending,
}
/// <summary>
/// List of all recognized submission display kinds
/// </summary>
public enum SubmissionType
{
[HumanReadable(LongName = "Edit", ShortName = "Edit")]
Edit,
[HumanReadable(LongName = "New Disc", ShortName = "New+Disc")]
NewDisc,
[HumanReadable(LongName = "Verification", ShortName = "Verification")]
Verification
}
/// <summary>
/// List of system categories
/// </summary>

View File

@@ -2513,6 +2513,70 @@ namespace SabreTools.RedumpLib.Data
#endregion
#region Submission Type
/// <summary>
/// Get the human readable name for a SubmissionType
/// </summary>
/// <param name="sortDirection"></param>
/// <returns></returns>
public static string? LongName(this SubmissionType sortDirection)
=> AttributeHelper<SubmissionType>.GetHumanReadableAttribute(sortDirection)?.LongName;
/// <summary>
/// Get the human readable name for a SubmissionType
/// </summary>
/// <param name="sortDirection"></param>
/// <returns></returns>
public static string? LongName(this SubmissionType? sortDirection)
=> AttributeHelper<SubmissionType?>.GetHumanReadableAttribute(sortDirection)?.LongName;
/// <summary>
/// Get the URL path part for a SubmissionType
/// </summary>
/// <param name="sortDirection"></param>
/// <returns></returns>
public static string? ShortName(this SubmissionType sortDirection)
=> AttributeHelper<SubmissionType>.GetHumanReadableAttribute(sortDirection)?.ShortName;
/// <summary>
/// Get the URL path part for a SubmissionType
/// </summary>
/// <param name="sortDirection"></param>
/// <returns></returns>
public static string? ShortName(this SubmissionType? sortDirection)
=> AttributeHelper<SubmissionType?>.GetHumanReadableAttribute(sortDirection)?.ShortName;
/// <summary>
/// Get the Region enum value for a given string
/// </summary>
/// <param name="sortDirection">String value to convert</param>
/// <returns>Region represented by the string, if possible</returns>
public static SubmissionType? ToSubmissionType(this string? sortDirection)
{
// No value means no match
if (sortDirection is null || sortDirection.Length == 0)
return null;
sortDirection = sortDirection.ToLowerInvariant();
var sortCategories = (SubmissionType[])Enum.GetValues(typeof(SubmissionType));
// Check short names
int index = Array.FindIndex(sortCategories, s => sortDirection == s.ShortName()?.ToLowerInvariant());
if (index > -1)
return sortCategories[index];
// Check long names
index = Array.FindIndex(sortCategories, s => sortDirection == s.LongName()?.ToLowerInvariant()
|| sortDirection == s.LongName()?.Replace(" ", string.Empty)?.ToLowerInvariant());
if (index > -1)
return sortCategories[index];
return null;
}
#endregion
#region System Category
/// <summary>

View File

@@ -18,6 +18,11 @@ namespace SabreTools.RedumpLib.Web
#region Top-Level Paths
/// <summary>
/// Path for about page
/// </summary>
private const string AboutPath = "about/";
/// <summary>
/// Path for BIOS datfile downloads
/// </summary>
@@ -26,12 +31,12 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Path for cuesheet pack downloads
/// </summary>
private const string CuesPath = @"cues/{0}/";
private const string CuesPath = @"cues/{0}";
/// <summary>
/// Path for datfile downloads
/// </summary>
private const string DatfilePath = @"datfile/{0}/";
private const string DatfilePath = @"datfile/{0}";
/// <summary>
/// Path for individual disc pages
@@ -51,7 +56,7 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Path for key pack downloads
/// </summary>
private const string KeysPath = @"keys/{0}/";
private const string KeysPath = @"keys/{0}";
/// <summary>
/// Path for discs queue
@@ -66,7 +71,7 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Path for SBI pack downloads
/// </summary>
private const string SbiPath = @"sbi/{0}/";
private const string SbiPath = @"sbi/{0}";
#endregion
@@ -74,6 +79,19 @@ namespace SabreTools.RedumpLib.Web
#endregion
/// <summary>
/// Build a /about/ path URL
/// </summary>
public static string BuildAboutUrl()
{
var sb = new StringBuilder();
sb.Append(SiteBaseUrl);
sb.Append(AboutPath);
return sb.ToString();
}
/// <summary>
/// Build a /static/bios/ path URL
/// </summary>
@@ -365,13 +383,17 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Build a /downloads/ path URL
/// </summary>
public static string BuildDownloadsUrl()
/// <param name="database">Target database download</param>
public static string BuildDownloadsUrl(bool? database = null)
{
var sb = new StringBuilder();
sb.Append(SiteBaseUrl);
sb.Append(DownloadsPath);
if (database == true)
sb.Append("database");
return sb.ToString();
}
@@ -381,6 +403,7 @@ namespace SabreTools.RedumpLib.Web
/// <param name="packType">Pack type</param>
/// <param name="system">System for download</param>
/// <remarks>Does not check for invalid systems</remarks>
/// TODO: Handle download_dat_variant?
public static string BuildPackUrl(PackType packType, PhysicalSystem system)
{
var sb = new StringBuilder();
@@ -408,12 +431,94 @@ namespace SabreTools.RedumpLib.Web
/// <summary>
/// Build a /queue/ path URL
/// </summary>
public static string BuildQueueUrl()
/// <param name="discId">Add disc ID to filter, null to omit</param>
/// <param name="isDiscHistory">Set disc history status, null to omit</param>
/// <param name="order">Add sorting direction, null to omit</param>
/// <param name="page">Page number, null to omit</param>
/// <param name="sort">Add sorting type, null to omit</param>
/// <param name="status">Add status to filter, null to omit</param>
/// <param name="submitter">Add submitter name to filter, null to omit</param>
/// <param name="subType">Add submission type to filter, null to omit</param>
/// <param name="system">Add system to filter, null to omit</param>
/// <remarks>Ordered according to site source code</remarks>
public static string BuildQueueUrl(
long? discId = null,
bool? isDiscHistory = null,
SortDirection? order = null,
long? page = null,
SortCategory? sort = null,
DumpStatus? status = null,
string? submitter = null,
SubmissionType? subType = null,
PhysicalSystem? system = null)
{
var sb = new StringBuilder();
sb.Append(SiteBaseUrl);
sb.Append(QueuePath);
sb.Append('?');
// Status
string? statusName = status.LongName();
if (statusName is not null)
sb.Append($"status={statusName}&");
// Submission Type
string? subTypeName = subType.ShortName();
if (subTypeName is not null)
sb.Append($"sub_type={subTypeName}&");
// System
string? systemName = system.ShortName();
if (systemName is not null)
sb.Append($"system={systemName}&");
// Submitter
if (submitter is not null)
sb.Append($"submitter={submitter}&");
// Disc ID
if (discId is not null)
sb.Append($"disc_id={discId}&");
// Sorting
switch (sort)
{
case SortCategory.Title:
case SortCategory.Added:
case SortCategory.Region:
case SortCategory.System:
case SortCategory.Version:
case SortCategory.Edition:
case SortCategory.Language:
case SortCategory.Languages:
case SortCategory.Serial:
case SortCategory.Status:
case SortCategory.Modified:
sb.Append($"sort={sort.ShortName()}&");
break;
default: break;
}
// Sort Direction
switch (order)
{
case SortDirection.Ascending:
case SortDirection.Descending:
sb.Append($"order={order.ShortName()}&");
break;
default: break;
}
// Page Number
if (page is not null)
sb.Append($"page={page}");
// Is Disc History
if (isDiscHistory is not null)
sb.Append($"is_disc_history={isDiscHistory.ToYesNo().LongName()}&");
return sb.ToString();
}