diff --git a/SabreTools.RedumpLib.Test/Endpoints/DiscsTests.cs b/SabreTools.RedumpLib.Test/Endpoints/DiscsTests.cs new file mode 100644 index 0000000..b42dd22 --- /dev/null +++ b/SabreTools.RedumpLib.Test/Endpoints/DiscsTests.cs @@ -0,0 +1,74 @@ +using SabreTools.RedumpLib.Data; +using Xunit; + +namespace SabreTools.RedumpLib.Test.Endpoints +{ + public class DiscsTests + { + #region BuildUrl + + [Fact] + public void BuildUrl_DumperWithPages_Builds() + { + var endpoint = new RedumpLib.Endpoints.Discs + { + Dumper = "user", + Page = 3, + }; + + string actual = endpoint.BuildUrl(); + Assert.Equal("https://redump.info/discs?dumper=user&page=3", actual); + } + + [Fact] + public void BuildUrl_DumperLastModifiedWithPages_Builds() + { + var endpoint = new RedumpLib.Endpoints.Discs + { + Dumper = "user", + Sort = SortCategory.Modified, + Order = SortDirection.Descending, + Page = 3, + }; + + string actual = endpoint.BuildUrl(); + Assert.Equal("https://redump.info/discs?dumper=user&sort=modified&order=desc&page=3", actual); + } + + [Fact] + public void BuildUrl_LastModifiedWithPages_Builds() + { + var endpoint = new RedumpLib.Endpoints.Discs + { + Sort = SortCategory.Modified, + Order = SortDirection.Descending, + Page = 3, + }; + + string actual = endpoint.BuildUrl(); + Assert.Equal("https://redump.info/discs?sort=modified&order=desc&page=3", actual); + } + + [Theory] + [InlineData("", "https://redump.info/discs?q=&page=3")] + [InlineData("simple", "https://redump.info/discs?q=simple&page=3")] + [InlineData("search-format", "https://redump.info/discs?q=search-format&page=3")] + [InlineData("invalid format", "https://redump.info/discs?q=invalid format&page=3")] + [InlineData("extra/path", "https://redump.info/discs?q=extra/path&page=3")] + public void BuildUrl_QuicksearchWithPages_Builds(string query, string expected) + { + var endpoint = new RedumpLib.Endpoints.Discs + { + Query = query, + Page = 3, + }; + + string actual = endpoint.BuildUrl(); + Assert.Equal(expected, actual); + } + + // TODO: Implement more extensive discs tests + + #endregion + } +} diff --git a/SabreTools.RedumpLib.Test/Web/UrlBuilderTests.cs b/SabreTools.RedumpLib.Test/Web/UrlBuilderTests.cs index 69b5b46..cbc9ec8 100644 --- a/SabreTools.RedumpLib.Test/Web/UrlBuilderTests.cs +++ b/SabreTools.RedumpLib.Test/Web/UrlBuilderTests.cs @@ -42,45 +42,6 @@ namespace SabreTools.RedumpLib.Test.Web #endregion - #region BuildDiscsUrl - - [Fact] - public void BuildDiscsUrl_DumperWithPages_Builds() - { - string actual = UrlBuilder.BuildDiscsUrl(dumper: "user", page: 3); - Assert.Equal("https://redump.info/discs?dumper=user&page=3", actual); - } - - [Fact] - public void BuildDiscsUrl_DumperLastModifiedWithPages_Builds() - { - string actual = UrlBuilder.BuildDiscsUrl(dumper: "user", sort: SortCategory.Modified, order: SortDirection.Descending, page: 3); - Assert.Equal("https://redump.info/discs?dumper=user&sort=modified&order=desc&page=3", actual); - } - - [Fact] - public void BuildDiscsUrl_LastModifiedWithPages_Builds() - { - string actual = UrlBuilder.BuildDiscsUrl(sort: SortCategory.Modified, order: SortDirection.Descending, page: 3); - Assert.Equal("https://redump.info/discs?sort=modified&order=desc&page=3", actual); - } - - [Theory] - [InlineData("", "https://redump.info/discs?q=&page=3")] - [InlineData("simple", "https://redump.info/discs?q=simple&page=3")] - [InlineData("search-format", "https://redump.info/discs?q=search-format&page=3")] - [InlineData("invalid format", "https://redump.info/discs?q=invalid format&page=3")] - [InlineData("extra/path", "https://redump.info/discs?q=extra/path&page=3")] - public void BuildDiscsUrl_QuicksearchWithPages_Builds(string query, string expected) - { - string actual = UrlBuilder.BuildDiscsUrl(query: query, page: 3); - Assert.Equal(expected, actual); - } - - // TODO: Implement more extensive discs tests - - #endregion - #region BuildDownloadsUrl [Theory] diff --git a/SabreTools.RedumpLib/Endpoints/Discs.cs b/SabreTools.RedumpLib/Endpoints/Discs.cs new file mode 100644 index 0000000..81d707a --- /dev/null +++ b/SabreTools.RedumpLib/Endpoints/Discs.cs @@ -0,0 +1,303 @@ +using System; +using System.Text; +using Newtonsoft.Json; +using SabreTools.RedumpLib.Data; + +namespace SabreTools.RedumpLib.Endpoints +{ + [JsonObject("discs")] + public class Discs + { + [JsonProperty("system")] + public PhysicalSystem? System { get; set; } + + [JsonProperty("region")] + public RegionCode? Region { get; set; } + + [JsonProperty("language")] + public LanguageCode? Language { get; set; } + + [JsonProperty("media")] + public MediaType? Media { get; set; } + + [JsonProperty("category")] + public DiscCategory? Category { get; set; } + + [JsonProperty("status")] + public DumpStatus? Status { get; set; } + + [JsonProperty("letter")] + public char? Letter { get; set; } + + [JsonProperty("dumper")] + public string? Dumper { get; set; } + + [JsonProperty("title")] + public string? Title { get; set; } + + [JsonProperty("title_exact")] + public bool? TitleExact { get; set; } + + [JsonProperty("title_foreign")] + public string? TitleForeign { get; set; } + + [JsonProperty("title_foreign_exact")] + public bool? TitleForeignExact { get; set; } + + [JsonProperty("serial")] + public string? Serial { get; set; } + + [JsonProperty("serial_exact")] + public bool? SerialExact { get; set; } + + [JsonProperty("edition")] + public string? Edition { get; set; } + + [JsonProperty("edition_exact")] + public bool? EditionExact { get; set; } + + [JsonProperty("barcode")] + public string? Barcode { get; set; } + + [JsonProperty("barcode_exact")] + public bool? BarcodeExact { get; set; } + + [JsonProperty("universal_hash")] + public string? UniversalHash { get; set; } + + [JsonProperty("tracks_min")] + public long? TracksMin { get; set; } + + [JsonProperty("tracks_max")] + public long? TracksMax { get; set; } + + [JsonProperty("errors_min")] + public long? ErrorsMin { get; set; } + + [JsonProperty("errors_max")] + public long? ErrorsMax { get; set; } + + [JsonProperty("edc")] + public YesNo? Edc { get; set; } + + [JsonProperty("protection")] + public string? Protection { get; set; } + + [JsonProperty("comments")] + public string? Comments { get; set; } + + [JsonProperty("contents")] + public string? Contents { get; set; } + + [JsonProperty("mastering_code")] + public string? MasteringCode { get; set; } + + [JsonProperty("mastering_sid")] + public string? MasteringSid { get; set; } + + [JsonProperty("toolstamp")] + public string? Toolstamp { get; set; } + + [JsonProperty("mould_sid")] + public string? MouldSid { get; set; } + + [JsonProperty("additional_mould")] + public string? AdditionalMould { get; set; } + + [JsonProperty("ringcode")] + public string? Ringcode { get; set; } + + [JsonProperty("offset")] + public long? Offset { get; set; } + + [JsonProperty("q")] + public string? Query { get; set; } + + [JsonProperty("sort")] + public SortCategory? Sort { get; set; } + + [JsonProperty("order")] + public SortDirection? Order { get; set; } + + [JsonProperty("page")] + public long? Page { get; set; } + + [JsonProperty("advanced")] + public bool? Advanced { get; set; } + + /// + /// Build a /discs/ path URL + /// + public string BuildUrl() + { + var ub = new UriBuilder + { + Scheme = "https", + Host = "redump.info", + Path = "discs", + Query = BuildQuery(), + }; + + return ub.ToString(); + } + + /// + /// Build a /discs/ path query + /// + /// Ordered according to site source code + private string BuildQuery() + { + var sb = new StringBuilder(); + + // System + string? system = System?.Code; + if (system is not null) + sb.Append($"system={system}&"); + + // Region + string? region = Region?.Code; + if (region is not null) + sb.Append($"region={region}&"); + + // Language + string? langauge = Language?.TwoLetterCode; + if (langauge is not null) + sb.Append($"language={langauge}&"); + + // Media + string? media = Media.ShortName(); + if (media is not null) + sb.Append($"media={media}&"); + + // Category + string? category = Category.LongName(); + if (category is not null) + sb.Append($"category={category}&"); + + // Status + string? status = Status.LongName(); + if (status is not null) + sb.Append($"status={status}&"); + + // Letter + if (Letter is not null) + sb.Append($"letter={char.ToUpperInvariant(Letter.Value)}&"); + + // Dumper + if (Dumper is not null) + sb.Append($"dumper={Dumper}&"); + + // Title + if (Title is not null) + sb.Append($"title={Title}&"); + if (Title is not null && TitleExact is not null) + sb.Append($"title_exact={TitleExact.ToYesNo().LongName()}&"); + + // Foreign Title + if (TitleForeign is not null) + sb.Append($"title_foreign={TitleForeign}&"); + if (TitleForeign is not null && TitleForeignExact is not null) + sb.Append($"title_foreign_exact={TitleForeignExact.ToYesNo().LongName()}&"); + + // Serial + if (Serial is not null) + sb.Append($"serial={Serial}&"); + if (Serial is not null && SerialExact is not null) + sb.Append($"serial_exact={SerialExact.ToYesNo().LongName()}&"); + + // Edition + if (Edition is not null) + sb.Append($"edition={Edition}&"); + if (Edition is not null && EditionExact is not null) + sb.Append($"edition_exact={EditionExact.ToYesNo().LongName()}&"); + + // Barcode + if (Barcode is not null) + sb.Append($"barcode={Barcode}&"); + if (Barcode is not null && BarcodeExact is not null) + sb.Append($"barcode_exact={BarcodeExact.ToYesNo().LongName()}&"); + + // Universal Hash + if (UniversalHash is not null) + sb.Append($"universal_hash={UniversalHash}&"); + + // Track Count + if (TracksMin is not null) + sb.Append($"tracks_min={TracksMin}&"); + if (TracksMax is not null) + sb.Append($"tracks_max={TracksMax}&"); + + // Error Count + if (ErrorsMin is not null) + sb.Append($"errors_min={ErrorsMin}&"); + if (ErrorsMax is not null) + sb.Append($"errors_max={ErrorsMax}&"); + + // EDC + if (Edc is not null && Edc != YesNo.NULL) + sb.Append($"edc={Edc.LongName()}&"); + + // Protection + if (Protection is not null) + sb.Append($"protection={Protection}&"); + + // Comments + if (Comments is not null) + sb.Append($"comments={Comments}&"); + + // Contents + if (Contents is not null) + sb.Append($"contents={Contents}&"); + + // Mastering Code + if (MasteringCode is not null) + sb.Append($"mastering_code={MasteringCode}&"); + + // Mastering SID + if (MasteringSid is not null) + sb.Append($"mastering_sid={MasteringSid}&"); + + // Toolstamp + if (Toolstamp is not null) + sb.Append($"toolstamp={Toolstamp}&"); + + // Mould SID + if (MouldSid is not null) + sb.Append($"mould_sid={MouldSid}&"); + + // Additional Mould + if (AdditionalMould is not null) + sb.Append($"additional_mould={AdditionalMould}&"); + + // Ringcode + if (Ringcode is not null) + sb.Append($"ringcode={Ringcode}&"); + + // Offset + if (Offset is not null) + sb.Append($"offset={Offset}&"); + + // General Query + if (Query is not null) + sb.Append($"q={Query}&"); + + // Sorting + if (Sort is not null && Enum.IsDefined(typeof(SortCategory), Sort)) + sb.Append($"sort={Sort.ShortName()}&"); + + // Sort Direction + if (Order is not null && Enum.IsDefined(typeof(SortDirection), Order)) + sb.Append($"order={Order.ShortName()}&"); + + // Page Number + if (Page is not null) + sb.Append($"page={Page}"); + + // Advanced + if (Advanced is not null) + sb.Append($"advanced={(Advanced.Value ? "1" : "0")}&"); + + return sb.ToString(); + } + } +} diff --git a/SabreTools.RedumpLib/Web/Client.cs b/SabreTools.RedumpLib/Web/Client.cs index 80023cb..c7aa65d 100644 --- a/SabreTools.RedumpLib/Web/Client.cs +++ b/SabreTools.RedumpLib/Web/Client.cs @@ -577,46 +577,50 @@ namespace SabreTools.RedumpLib.Web if (query is not null) query = NormalizeQuery(query); - string url = UrlBuilder.BuildDiscsUrl( - additionalMould, - advanced, - barcode, - barcodeExact, - category, - comments, - contents, - dumper, - edc, - edition, - editionExact, - errorsMax, - errorsMin, - language, - letter, - masteringCode, - masteringSid, - media, - mouldSid, - offset, - order, - page, - protection, - query, - region, - ringcode, - serial, - serialExact, - sort, - status, - system, - title, - titleExact, - titleForeign, - titleForeignExact, - toolstamp, - tracksMax, - tracksMin, - universalHash); + var endpoint = new Endpoints.Discs + { + System = system, + Region = region, + Language = language, + Media = media, + Category = category, + Status = status, + Letter = letter, + Dumper = dumper, + Title = title, + TitleExact = titleExact, + TitleForeign = titleForeign, + TitleForeignExact = titleForeignExact, + Serial = serial, + SerialExact = serialExact, + Edition = edition, + EditionExact = editionExact, + Barcode = barcode, + BarcodeExact = barcodeExact, + UniversalHash = universalHash, + TracksMin = tracksMin, + TracksMax = tracksMax, + ErrorsMin = errorsMin, + ErrorsMax = errorsMax, + Edc = edc, + Protection = protection, + Comments = comments, + Contents = contents, + MasteringCode = masteringCode, + MasteringSid = masteringSid, + Toolstamp = toolstamp, + MouldSid = mouldSid, + AdditionalMould = additionalMould, + Ringcode = ringcode, + Offset = offset, + Query = query, + Sort = sort, + Order = order, + Page = page, + Advanced = advanced, + }; + + string url = endpoint.BuildUrl(); List ids = []; diff --git a/SabreTools.RedumpLib/Web/UrlBuilder.cs b/SabreTools.RedumpLib/Web/UrlBuilder.cs index efb0926..ab27129 100644 --- a/SabreTools.RedumpLib/Web/UrlBuilder.cs +++ b/SabreTools.RedumpLib/Web/UrlBuilder.cs @@ -81,141 +81,6 @@ namespace SabreTools.RedumpLib.Web return ub.ToString(); } - /// - /// Build a /discs/ path URL - /// - /// Add additional mould to filter, null to omit - /// Set advanced search status, null to omit - /// Add barcode to filter, null to omit - /// Set exact barcode handling, null to omit - /// Add category to filter, null to omit - /// Add comments to filter, null to omit - /// Add contents to filter, null to omit - /// Add dumper name to filter, null to omit - /// Add EDC status to filter, null to omit - /// Add edition to filter, null to omit - /// Set exact edition handling, null to omit - /// Add maximum error count to filter, null to omit - /// Add minimum error count to filter, null to omit - /// Add language to filter, null to omit - /// Starts with upper-case letter or '#' for numbers, null to omit - /// Add mastering code to filter, null to omit - /// Add mastering SID to filter, null to omit - /// Add media type to filter, null to omit - /// Add mould SID to filter, null to omit - /// Add offset to filter, null to omit - /// Add sorting direction, null to omit - /// Page number, null to omit - /// Add protection to filter, null to omit - /// Generic text query to filter, null to omit - /// Add region to filter, null to omit - /// Add ringcode to filter, null to omit - /// Add serial to filter, null to omit - /// Set exact serial handling, null to omit - /// Add sorting type, null to omit - /// Add status to filter, null to omit - /// Add system to filter, null to omit - /// Add title to filter, null to omit - /// Set exact title handling, null to omit - /// Add foreign title to filter, null to omit - /// Set exact foreign title handling, null to omit - /// Add toolstamp to filter, null to omit - /// Add maximum track count to filter, null to omit - /// Add minimum track count to filter, null to omit - /// Add universal hash to filter, null to omit - /// Ordered according to site source code - public static string BuildDiscsUrl( - string? additionalMould = null, - bool? advanced = null, - string? barcode = null, - bool? barcodeExact = null, - DiscCategory? category = null, - string? comments = null, - string? contents = null, - string? dumper = null, - YesNo? edc = null, - string? edition = null, - bool? editionExact = null, - long? errorsMax = null, - long? errorsMin = null, - LanguageCode? language = null, - char? letter = null, - string? masteringCode = null, - string? masteringSid = null, - MediaType? media = null, - string? mouldSid = null, - long? offset = null, - SortDirection? order = null, - long? page = null, - string? protection = null, - string? query = null, - RegionCode? region = null, - string? ringcode = null, - string? serial = null, - bool? serialExact = null, - SortCategory? sort = null, - DumpStatus? status = null, - PhysicalSystem? system = null, - string? title = null, - bool? titleExact = null, - string? titleForeign = null, - bool? titleForeignExact = null, - string? toolstamp = null, - long? tracksMax = null, - long? tracksMin = null, - string? universalHash = null) - { - var ub = new UriBuilder - { - Scheme = "https", - Host = "redump.info", - Path = "discs", - Query = BuildDiscsQuery( - additionalMould, - advanced, - barcode, - barcodeExact, - category, - comments, - contents, - dumper, - edc, - edition, - editionExact, - errorsMax, - errorsMin, - language, - letter, - masteringCode, - masteringSid, - media, - mouldSid, - offset, - order, - page, - protection, - query, - region, - ringcode, - serial, - serialExact, - sort, - status, - system, - title, - titleExact, - titleForeign, - titleForeignExact, - toolstamp, - tracksMax, - tracksMin, - universalHash - ), - }; - - return ub.ToString(); - } - /// /// Build a /downloads/ path URL /// @@ -370,243 +235,6 @@ namespace SabreTools.RedumpLib.Web #region Query String Builders - /// - /// Build a /discs/ path query - /// - /// Add additional mould to filter, null to omit - /// Set advanced search status, null to omit - /// Add barcode to filter, null to omit - /// Set exact barcode handling, null to omit - /// Add category to filter, null to omit - /// Add comments to filter, null to omit - /// Add contents to filter, null to omit - /// Add dumper name to filter, null to omit - /// Add EDC status to filter, null to omit - /// Add edition to filter, null to omit - /// Set exact edition handling, null to omit - /// Add maximum error count to filter, null to omit - /// Add minimum error count to filter, null to omit - /// Add language to filter, null to omit - /// Starts with upper-case letter or '#' for numbers, null to omit - /// Add mastering code to filter, null to omit - /// Add mastering SID to filter, null to omit - /// Add media type to filter, null to omit - /// Add mould SID to filter, null to omit - /// Add offset to filter, null to omit - /// Add sorting direction, null to omit - /// Page number, null to omit - /// Add protection to filter, null to omit - /// Generic text query to filter, null to omit - /// Add region to filter, null to omit - /// Add ringcode to filter, null to omit - /// Add serial to filter, null to omit - /// Set exact serial handling, null to omit - /// Add sorting type, null to omit - /// Add status to filter, null to omit - /// Add system to filter, null to omit - /// Add title to filter, null to omit - /// Set exact title handling, null to omit - /// Add foreign title to filter, null to omit - /// Set exact foreign title handling, null to omit - /// Add toolstamp to filter, null to omit - /// Add maximum track count to filter, null to omit - /// Add minimum track count to filter, null to omit - /// Add universal hash to filter, null to omit - /// Ordered according to site source code - private static string BuildDiscsQuery( - string? additionalMould, - bool? advanced, - string? barcode, - bool? barcodeExact, - DiscCategory? category, - string? comments, - string? contents, - string? dumper, - YesNo? edc, - string? edition, - bool? editionExact, - long? errorsMax, - long? errorsMin, - LanguageCode? language, - char? letter, - string? masteringCode, - string? masteringSid, - MediaType? media, - string? mouldSid, - long? offset, - SortDirection? order, - long? page, - string? protection, - string? query, - RegionCode? region, - string? ringcode, - string? serial, - bool? serialExact, - SortCategory? sort, - DumpStatus? status, - PhysicalSystem? system, - string? title, - bool? titleExact, - string? titleForeign, - bool? titleForeignExact, - string? toolstamp, - long? tracksMax, - long? tracksMin, - string? universalHash) - { - var sb = new StringBuilder(); - - // System - string? systemName = system?.Code; - if (systemName is not null) - sb.Append($"system={systemName}&"); - - // Region - string? regionName = region?.Code; - if (regionName is not null) - sb.Append($"region={regionName}&"); - - // Language - string? languageName = language?.TwoLetterCode; - if (languageName is not null) - sb.Append($"language={languageName}&"); - - // Media - string? mediaName = media.ShortName(); - if (mediaName is not null) - sb.Append($"media={mediaName}&"); - - // Category - string? categoryName = category.LongName(); - if (categoryName is not null) - sb.Append($"category={categoryName}&"); - - // Status - string? statusName = status.LongName(); - if (statusName is not null) - sb.Append($"status={statusName}&"); - - // Letter - if (letter is not null) - sb.Append($"letter={char.ToUpperInvariant(letter.Value)}&"); - - // Dumper - if (dumper is not null) - sb.Append($"dumper={dumper}&"); - - // Title - if (title is not null) - sb.Append($"title={title}&"); - if (title is not null && titleExact is not null) - sb.Append($"title_exact={titleExact.ToYesNo().LongName()}&"); - - // Foreign Title - if (titleForeign is not null) - sb.Append($"title_foreign={titleForeign}&"); - if (titleForeign is not null && titleForeignExact is not null) - sb.Append($"title_foreign_exact={titleForeignExact.ToYesNo().LongName()}&"); - - // Foreign Title - if (serial is not null) - sb.Append($"serial={serial}&"); - if (serial is not null && serialExact is not null) - sb.Append($"serial_exact={serialExact.ToYesNo().LongName()}&"); - - // Edition - if (edition is not null) - sb.Append($"edition={edition}&"); - if (edition is not null && editionExact is not null) - sb.Append($"edition_exact={editionExact.ToYesNo().LongName()}&"); - - // Barcode - if (barcode is not null) - sb.Append($"barcode={barcode}&"); - if (barcode is not null && barcodeExact is not null) - sb.Append($"barcode_exact={barcodeExact.ToYesNo().LongName()}&"); - - // Universal Hash - if (universalHash is not null) - sb.Append($"universal_hash={universalHash}&"); - - // Track Count - if (tracksMin is not null) - sb.Append($"tracks_min={tracksMin}&"); - if (tracksMax is not null) - sb.Append($"tracks_max={tracksMax}&"); - - // Error Count - if (errorsMin is not null) - sb.Append($"errors_min={errorsMin}&"); - if (errorsMax is not null) - sb.Append($"errors_max={errorsMax}&"); - - // EDC - if (edc is not null && edc != YesNo.NULL) - sb.Append($"edc={edc.LongName()}&"); - - // Protection - if (protection is not null) - sb.Append($"protection={protection}&"); - - // Comments - if (comments is not null) - sb.Append($"comments={comments}&"); - - // Contents - if (contents is not null) - sb.Append($"contents={contents}&"); - - // Mastering Code - if (masteringCode is not null) - sb.Append($"mastering_code={masteringCode}&"); - - // Mastering SID - if (masteringSid is not null) - sb.Append($"mastering_sid={masteringSid}&"); - - // Toolstamp - if (toolstamp is not null) - sb.Append($"toolstamp={toolstamp}&"); - - // Mould SID - if (mouldSid is not null) - sb.Append($"mould_sid={mouldSid}&"); - - // Additional Mould - if (additionalMould is not null) - sb.Append($"additional_mould={additionalMould}&"); - - // Ringcode - if (ringcode is not null) - sb.Append($"ringcode={ringcode}&"); - - // Ringcode - if (offset is not null) - sb.Append($"offset={offset}&"); - - // General Query - if (query is not null) - sb.Append($"q={query}&"); - - // Sorting - if (sort is not null && Enum.IsDefined(typeof(SortCategory), sort)) - sb.Append($"sort={sort.ShortName()}&"); - - // Sort Direction - if (order is not null && Enum.IsDefined(typeof(SortDirection), order)) - sb.Append($"order={order.ShortName()}&"); - - // Page Number - if (page is not null) - sb.Append($"page={page}"); - - // Advanced - if (advanced is not null) - sb.Append($"advanced={(advanced.Value ? "1" : "0")}&"); - - return sb.ToString(); - } - /// /// Build a /queue/ path query ///