mirror of
https://github.com/SabreTools/SabreTools.RedumpLib.git
synced 2026-07-08 18:16:25 +00:00
Sync with new queue URL syntax
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -142,6 +142,7 @@ namespace SabreTools.RedumpLib.Data
|
||||
DiscSubpath.Cuesheet,
|
||||
DiscSubpath.Edit,
|
||||
DiscSubpath.History,
|
||||
DiscSubpath.SBI,
|
||||
];
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user