mirror of
https://github.com/SabreTools/SabreTools.RedumpLib.git
synced 2026-11-15 17:01:37 +00:00
Add list endpoint information
This commit is contained in:
@@ -921,6 +921,113 @@ namespace SabreTools.RedumpLib.Test.Data
|
||||
|
||||
#endregion
|
||||
|
||||
#region List Subpath
|
||||
|
||||
/// <summary>
|
||||
/// Check that every ListSubpath has a long name provided
|
||||
/// </summary>
|
||||
/// <param name="listSubpath">ListSubpath value to check</param>
|
||||
/// <param name="expectNull">True to expect a null value, false otherwise</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(GenerateListSubpathTestData))]
|
||||
public void ListSubpath_LongName(ListSubpath? listSubpath, bool expectNull)
|
||||
{
|
||||
var actual = listSubpath.LongName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
else
|
||||
Assert.NotNull(actual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that every ListSubpath has a short name provided
|
||||
/// </summary>
|
||||
/// <param name="listSubpath">ListSubpath value to check</param>
|
||||
/// <param name="expectNull">True to expect a null value, false otherwise</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(GenerateListSubpathTestData))]
|
||||
public void ListSubpath_ShortName(ListSubpath? listSubpath, bool expectNull)
|
||||
{
|
||||
var actual = listSubpath.ShortName();
|
||||
|
||||
if (expectNull)
|
||||
Assert.Null(actual);
|
||||
else
|
||||
Assert.NotNull(actual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that every ListSubpath that has a short name that is unique
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ListSubpath_ShortName_NoDuplicates()
|
||||
{
|
||||
var fullListSubpaths = Enum.GetValues<ListSubpath>().Cast<ListSubpath>().ToList();
|
||||
var filteredListSubpaths = new Dictionary<string, ListSubpath?>();
|
||||
|
||||
int totalCount = 0;
|
||||
foreach (ListSubpath? listSubpath in fullListSubpaths)
|
||||
{
|
||||
var code = listSubpath.ShortName();
|
||||
if (string.IsNullOrEmpty(code))
|
||||
continue;
|
||||
|
||||
// Throw if the code already exists
|
||||
if (filteredListSubpaths.ContainsKey(code))
|
||||
throw new DuplicateNameException($"Code {code} already in dictionary");
|
||||
|
||||
filteredListSubpaths[code] = listSubpath;
|
||||
totalCount++;
|
||||
}
|
||||
|
||||
Assert.Equal(totalCount, filteredListSubpaths.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check that every ListSubpath can be mapped from a string
|
||||
/// </summary>
|
||||
/// <param name="listSubpath">ListSubpath value to check</param>
|
||||
/// <param name="expectNull">True to expect a null value, false otherwise</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(GenerateListSubpathTestData))]
|
||||
public void ListSubpath_ToListSubpath(ListSubpath? listSubpath, bool expectNull)
|
||||
{
|
||||
string? longName = listSubpath.LongName();
|
||||
string? longNameSpaceless = longName?.Replace(" ", string.Empty);
|
||||
|
||||
var actualNormal = longName.ToListSubpath();
|
||||
var actualSpaceless = longNameSpaceless.ToListSubpath();
|
||||
|
||||
if (expectNull)
|
||||
{
|
||||
Assert.Null(actualNormal);
|
||||
Assert.Null(actualSpaceless);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Equal(listSubpath, actualNormal);
|
||||
Assert.Equal(listSubpath, actualSpaceless);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a test set of ListSubpath values
|
||||
/// </summary>
|
||||
/// <returns>MemberData-compatible list of ListSubpath values</returns>
|
||||
public static TheoryData<ListSubpath?, bool> GenerateListSubpathTestData()
|
||||
{
|
||||
var testData = new TheoryData<ListSubpath?, bool>() { { null, true } };
|
||||
foreach (ListSubpath? listSubpath in Enum.GetValues<ListSubpath>().Cast<ListSubpath?>())
|
||||
{
|
||||
testData.Add(listSubpath, false);
|
||||
}
|
||||
|
||||
return testData;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Media Type
|
||||
|
||||
/// <summary>
|
||||
|
||||
75
SabreTools.RedumpLib.Test/Endpoints/ListTests.cs
Normal file
75
SabreTools.RedumpLib.Test/Endpoints/ListTests.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using SabreTools.RedumpLib.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.RedumpLib.Test.Endpoints
|
||||
{
|
||||
public class ListTests
|
||||
{
|
||||
#region BuildUrl
|
||||
|
||||
[Fact]
|
||||
public void BuildUrl_MissingUsername_DefaultEmpty()
|
||||
{
|
||||
var endpoint = new RedumpLib.Endpoints.List();
|
||||
string actual = endpoint.BuildUrl();
|
||||
Assert.Equal($"https://redump.info/list/", actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildUrl_Subpath_Builds()
|
||||
{
|
||||
// Create a base endpoint and then modify the fields
|
||||
var endpoint = new RedumpLib.Endpoints.List { Username = "user" };
|
||||
|
||||
// Invalid subpath, no system
|
||||
endpoint.Subpath = null;
|
||||
endpoint.System = null;
|
||||
string actual = endpoint.BuildUrl();
|
||||
Assert.Equal("https://redump.info/list/user", actual);
|
||||
|
||||
// Invalid subpath, valid system
|
||||
endpoint.Subpath = null;
|
||||
endpoint.System = PhysicalSystem.AcornArchimedesAndRiscPC;
|
||||
actual = endpoint.BuildUrl();
|
||||
Assert.Equal("https://redump.info/list/user/ARCH", actual);
|
||||
|
||||
// Have subpath, no system
|
||||
endpoint.Subpath = ListSubpath.Have;
|
||||
endpoint.System = null;
|
||||
actual = endpoint.BuildUrl();
|
||||
Assert.Equal("https://redump.info/list/have/user", actual);
|
||||
|
||||
// Have subpath, valid system
|
||||
endpoint.Subpath = ListSubpath.Have;
|
||||
endpoint.System = PhysicalSystem.AcornArchimedesAndRiscPC;
|
||||
actual = endpoint.BuildUrl();
|
||||
Assert.Equal("https://redump.info/list/have/user/ARCH", actual);
|
||||
|
||||
// Cuesheets subpath, no system
|
||||
endpoint.Subpath = ListSubpath.Cuesheets;
|
||||
endpoint.System = null;
|
||||
actual = endpoint.BuildUrl();
|
||||
Assert.Equal("https://redump.info/list/cues/user", actual);
|
||||
|
||||
// Cuesheets subpath, valid system
|
||||
endpoint.Subpath = ListSubpath.Cuesheets;
|
||||
endpoint.System = PhysicalSystem.AcornArchimedesAndRiscPC;
|
||||
actual = endpoint.BuildUrl();
|
||||
Assert.Equal("https://redump.info/list/cues/user/ARCH", actual);
|
||||
|
||||
// Datfile subpath, no system
|
||||
endpoint.Subpath = ListSubpath.Datfile;
|
||||
endpoint.System = null;
|
||||
actual = endpoint.BuildUrl();
|
||||
Assert.Equal("https://redump.info/list/datfile/user", actual);
|
||||
|
||||
// Datfile subpath, valid system
|
||||
endpoint.Subpath = ListSubpath.Datfile;
|
||||
endpoint.System = PhysicalSystem.AcornArchimedesAndRiscPC;
|
||||
actual = endpoint.BuildUrl();
|
||||
Assert.Equal("https://redump.info/list/datfile/user/ARCH", actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,21 @@ namespace SabreTools.RedumpLib.Data
|
||||
VerifiedGreen = 5,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of all list subpaths
|
||||
/// </summary>
|
||||
public enum ListSubpath
|
||||
{
|
||||
[HumanReadable(LongName = "Have", ShortName = "have")]
|
||||
Have = 1,
|
||||
|
||||
[HumanReadable(LongName = "Cuesheets", ShortName = "cues")]
|
||||
Cuesheets = 2,
|
||||
|
||||
[HumanReadable(LongName = "Datfile", ShortName = "datfile")]
|
||||
Datfile = 3,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of all site-supported media types
|
||||
/// </summary>
|
||||
|
||||
@@ -241,10 +241,10 @@ namespace SabreTools.RedumpLib.Data
|
||||
=> AttributeHelper<DiscSubpath?>.GetHumanReadableAttribute(discSubpath)?.ShortName;
|
||||
|
||||
/// <summary>
|
||||
/// Get the Region enum value for a given string
|
||||
/// Get the DiscSubpath enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="discSubpath">String value to convert</param>
|
||||
/// <returns>Region represented by the string, if possible</returns>
|
||||
/// <returns>DiscSubpath represented by the string, if possible</returns>
|
||||
public static DiscSubpath? ToDiscSubpath(this string? discSubpath)
|
||||
{
|
||||
// No value means no match
|
||||
@@ -374,6 +374,70 @@ namespace SabreTools.RedumpLib.Data
|
||||
|
||||
#endregion
|
||||
|
||||
#region List Subpath
|
||||
|
||||
/// <summary>
|
||||
/// Get the human readable name for a ListSubpath
|
||||
/// </summary>
|
||||
/// <param name="listSubpath"></param>
|
||||
/// <returns></returns>
|
||||
public static string? LongName(this ListSubpath listSubpath)
|
||||
=> AttributeHelper<ListSubpath>.GetHumanReadableAttribute(listSubpath)?.LongName;
|
||||
|
||||
/// <summary>
|
||||
/// Get the human readable name for a ListSubpath
|
||||
/// </summary>
|
||||
/// <param name="listSubpath"></param>
|
||||
/// <returns></returns>
|
||||
public static string? LongName(this ListSubpath? listSubpath)
|
||||
=> AttributeHelper<ListSubpath?>.GetHumanReadableAttribute(listSubpath)?.LongName;
|
||||
|
||||
/// <summary>
|
||||
/// Get the URL path part for a ListSubpath
|
||||
/// </summary>
|
||||
/// <param name="listSubpath"></param>
|
||||
/// <returns></returns>
|
||||
public static string? ShortName(this ListSubpath listSubpath)
|
||||
=> AttributeHelper<ListSubpath>.GetHumanReadableAttribute(listSubpath)?.ShortName;
|
||||
|
||||
/// <summary>
|
||||
/// Get the URL path part for a ListSubpath
|
||||
/// </summary>
|
||||
/// <param name="listSubpath"></param>
|
||||
/// <returns></returns>
|
||||
public static string? ShortName(this ListSubpath? listSubpath)
|
||||
=> AttributeHelper<ListSubpath?>.GetHumanReadableAttribute(listSubpath)?.ShortName;
|
||||
|
||||
/// <summary>
|
||||
/// Get the ListSubpath enum value for a given string
|
||||
/// </summary>
|
||||
/// <param name="listSubpath">String value to convert</param>
|
||||
/// <returns>ListSubpath represented by the string, if possible</returns>
|
||||
public static ListSubpath? ToListSubpath(this string? listSubpath)
|
||||
{
|
||||
// No value means no match
|
||||
if (listSubpath is null || listSubpath.Length == 0)
|
||||
return null;
|
||||
|
||||
listSubpath = listSubpath.ToLowerInvariant();
|
||||
var listSubpaths = (ListSubpath[])Enum.GetValues(typeof(ListSubpath));
|
||||
|
||||
// Check short names
|
||||
int index = Array.FindIndex(listSubpaths, s => listSubpath == s.ShortName()?.ToLowerInvariant());
|
||||
if (index > -1)
|
||||
return listSubpaths[index];
|
||||
|
||||
// Check long names
|
||||
index = Array.FindIndex(listSubpaths, s => listSubpath == s.LongName()?.ToLowerInvariant()
|
||||
|| listSubpath == s.LongName()?.Replace(" ", string.Empty)?.ToLowerInvariant());
|
||||
if (index > -1)
|
||||
return listSubpaths[index];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Media Type
|
||||
|
||||
/// <summary>
|
||||
|
||||
52
SabreTools.RedumpLib/Endpoints/List.cs
Normal file
52
SabreTools.RedumpLib/Endpoints/List.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using SabreTools.RedumpLib.Data;
|
||||
|
||||
namespace SabreTools.RedumpLib.Endpoints
|
||||
{
|
||||
// TODO: Implement download and client extensions for these paths
|
||||
[JsonObject("list")]
|
||||
public class List
|
||||
{
|
||||
[JsonProperty("subpath")]
|
||||
public ListSubpath? Subpath { get; set; }
|
||||
|
||||
[JsonProperty("username")]
|
||||
public string Username { get; set; } = string.Empty;
|
||||
|
||||
[JsonProperty("syscode")]
|
||||
public PhysicalSystem? System { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Build a /list/ path URL
|
||||
/// </summary>
|
||||
public string BuildUrl()
|
||||
{
|
||||
var ub = new UriBuilder
|
||||
{
|
||||
Scheme = "https",
|
||||
Host = "redump.info",
|
||||
Path = "list",
|
||||
};
|
||||
|
||||
switch (Subpath)
|
||||
{
|
||||
case ListSubpath.Have:
|
||||
case ListSubpath.Cuesheets:
|
||||
case ListSubpath.Datfile:
|
||||
ub.Path += $"/{Subpath.ShortName()}";
|
||||
break;
|
||||
|
||||
// Nothing else is valid as a subpath
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ub.Path += $"/{Username}";
|
||||
if (System?.Code is not null)
|
||||
ub.Path += $"/{System.Code}";
|
||||
|
||||
return ub.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user