From d050ced476b1ea0514a50befba543828ccea2ae7 Mon Sep 17 00:00:00 2001 From: Moley-Bot Date: Sun, 22 Feb 2026 10:34:18 +0000 Subject: [PATCH 1/3] Add collector for HarboroughDistrictCouncil Closes #133 Generated with Codex CLI by Moley-Bot --- .../Councils/HarboroughDistrictCouncil.cs | 230 ++++++++++++++++++ .../HarboroughDistrictCouncilTests.cs | 32 +++ 2 files changed, 262 insertions(+) create mode 100644 BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs create mode 100644 BinDays.Api.IntegrationTests/Collectors/Councils/HarboroughDistrictCouncilTests.cs diff --git a/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs b/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs new file mode 100644 index 0000000..51a8133 --- /dev/null +++ b/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs @@ -0,0 +1,230 @@ +namespace BinDays.Api.Collectors.Collectors.Councils; + +using BinDays.Api.Collectors.Collectors.Vendors; +using BinDays.Api.Collectors.Models; +using BinDays.Api.Collectors.Utilities; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text.Json; +using System.Text.RegularExpressions; + +/// +/// Collector implementation for Harborough District Council. +/// +internal sealed partial class HarboroughDistrictCouncil : GovUkCollectorBase, ICollector +{ + /// + public string Name => "Harborough District Council"; + + /// + public Uri WebsiteUrl => new("https://www.harborough.gov.uk/"); + + /// + public override string GovUkId => "harborough"; + + /// + /// The list of bin types for this collector. + /// + private readonly IReadOnlyCollection _binTypes = [ + new() + { + Name = "General Waste", + Colour = BinColour.Black, + Keys = [ "Non-recyclable waste" ], + }, + new() + { + Name = "Mixed Recycling", + Colour = BinColour.Blue, + Keys = [ "Recycling collection" ], + }, + new() + { + Name = "Garden Waste", + Colour = BinColour.Green, + Keys = [ "Garden waste" ], + }, + ]; + + private const string _baseUrl = "http://harborough.fccenvironment.co.uk/"; + private const string _forwardedProtoHeaderValue = "https"; + + /// + /// Regex for the bin days list items. + /// + [GeneratedRegex(@"
  • \s*(?[^<]+?)\s*]*>\s*(?[^<]+)\s*\s*
  • ", RegexOptions.IgnoreCase)] + private static partial Regex BinDaysRegex(); + + /// + /// Regex for the next scheduled bin collection block. + /// + [GeneratedRegex(@"block-your-next-scheduled-bin-collection-days"".*?(?
      .*?
    )", RegexOptions.Singleline)] + private static partial Regex BinDaysSectionRegex(); + + /// + public GetAddressesResponse GetAddresses(string postcode, ClientSideResponse? clientSideResponse) + { + // Prepare client-side request for getting addresses + if (clientSideResponse == null) + { + var requestBody = $$""" + { + "Postcode": "{{postcode}}" + } + """; + + var clientSideRequest = new ClientSideRequest + { + RequestId = 1, + Url = $"{_baseUrl}getAddress", + Method = "POST", + Headers = new() + { + { "user-agent", Constants.UserAgent }, + { "content-type", "application/json" }, + { "x-forwarded-proto", _forwardedProtoHeaderValue }, + }, + Body = requestBody, + Options = new ClientSideOptions + { + FollowRedirects = false, + }, + }; + + var getAddressesResponse = new GetAddressesResponse + { + NextClientSideRequest = clientSideRequest, + }; + + return getAddressesResponse; + } + // Process addresses from response + else if (clientSideResponse.RequestId == 1) + { + using var jsonDocument = JsonDocument.Parse(clientSideResponse.Content); + var addressElements = jsonDocument.RootElement.GetProperty("datas").EnumerateArray(); + + // Iterate through each address, and create a new address object + var addresses = new List
    (); + foreach (var addressElement in addressElements) + { + var uprn = addressElement.GetProperty("AccountSiteUprn").GetString()!; + + if (string.IsNullOrWhiteSpace(uprn)) + { + continue; + } + + var property = addressElement.GetProperty("SiteShortAddress").GetString()!.Trim(); + var addressLabel = addressElement.GetProperty("SiteShortAddressLabel").GetString()!.Trim(); + + // Uid format: "{uprn};{addressLabel}" + var address = new Address + { + Property = property, + Postcode = postcode, + Uid = $"{uprn};{addressLabel}", + }; + + addresses.Add(address); + } + + var getAddressesResponse = new GetAddressesResponse + { + Addresses = [.. addresses], + }; + + return getAddressesResponse; + } + + // Throw exception for invalid request + throw new InvalidOperationException("Invalid client-side request."); + } + + /// + public GetBinDaysResponse GetBinDays(Address address, ClientSideResponse? clientSideResponse) + { + // Prepare client-side request for getting bin days + if (clientSideResponse == null) + { + // Uid format: "{uprn};{addressLabel}" + var addressParts = address.Uid!.Split(';', 2); + var uprn = addressParts[0]; + var addressLabel = addressParts[1]; + + var requestBody = ProcessingUtilities.ConvertDictionaryToFormData(new Dictionary + { + { "Uprn", uprn }, + { "hiddenAddressLabel", addressLabel }, + }); + + var clientSideRequest = new ClientSideRequest + { + RequestId = 1, + Url = $"{_baseUrl}detail-address", + Method = "POST", + Headers = new() + { + { "user-agent", Constants.UserAgent }, + { "content-type", "application/x-www-form-urlencoded; charset=UTF-8" }, + { "x-forwarded-proto", _forwardedProtoHeaderValue }, + }, + Body = requestBody, + Options = new ClientSideOptions + { + FollowRedirects = false, + }, + }; + + var getBinDaysResponse = new GetBinDaysResponse + { + NextClientSideRequest = clientSideRequest, + }; + + return getBinDaysResponse; + } + // Process bin days from response + else if (clientSideResponse.RequestId == 1) + { + var binDaysContent = BinDaysSectionRegex().Match(clientSideResponse.Content).Groups["content"].Value; + var rawBinDays = BinDaysRegex().Matches(binDaysContent)!; + + // Iterate through each bin day, and create a new bin day object + var binDays = new List(); + foreach (Match rawBinDay in rawBinDays) + { + var service = rawBinDay.Groups["service"].Value.Trim(); + var collectionDate = rawBinDay.Groups["date"].Value.Trim(); + + var date = DateOnly.ParseExact( + collectionDate, + "d MMMM yyyy", + CultureInfo.InvariantCulture, + DateTimeStyles.None + ); + + var matchedBins = ProcessingUtilities.GetMatchingBins(_binTypes, service); + + var binDay = new BinDay + { + Date = date, + Address = address, + Bins = matchedBins, + }; + + binDays.Add(binDay); + } + + var getBinDaysResponse = new GetBinDaysResponse + { + BinDays = ProcessingUtilities.ProcessBinDays(binDays), + }; + + return getBinDaysResponse; + } + + // Throw exception for invalid request + throw new InvalidOperationException("Invalid client-side request."); + } +} diff --git a/BinDays.Api.IntegrationTests/Collectors/Councils/HarboroughDistrictCouncilTests.cs b/BinDays.Api.IntegrationTests/Collectors/Councils/HarboroughDistrictCouncilTests.cs new file mode 100644 index 0000000..a8cdda1 --- /dev/null +++ b/BinDays.Api.IntegrationTests/Collectors/Councils/HarboroughDistrictCouncilTests.cs @@ -0,0 +1,32 @@ +namespace BinDays.Api.IntegrationTests.Collectors.Councils; + +using BinDays.Api.Collectors.Collectors.Councils; +using BinDays.Api.IntegrationTests.Helpers; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +public class HarboroughDistrictCouncilTests +{ + private readonly IntegrationTestClient _client; + private readonly ITestOutputHelper _outputHelper; + private static readonly string _govUkId = new HarboroughDistrictCouncil().GovUkId; + + public HarboroughDistrictCouncilTests(ITestOutputHelper outputHelper) + { + _outputHelper = outputHelper; + _client = new IntegrationTestClient(outputHelper); + } + + [Theory] + [InlineData("LE17 5EG")] + public async Task GetBinDaysTest(string postcode) + { + await TestSteps.EndToEnd( + _client, + postcode, + _govUkId, + _outputHelper + ); + } +} From c16b5cc483ab6a976e90c5264984160cc0fb1dbf Mon Sep 17 00:00:00 2001 From: Moley-Bot Date: Sun, 22 Feb 2026 10:35:06 +0000 Subject: [PATCH 2/3] Auto-format code with dotnet format Formatted by Moley-Bot --- .../Councils/HarboroughDistrictCouncil.cs | 460 +++++++++--------- .../HarboroughDistrictCouncilTests.cs | 64 +-- 2 files changed, 262 insertions(+), 262 deletions(-) diff --git a/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs b/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs index 51a8133..b4b8f5e 100644 --- a/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs +++ b/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs @@ -1,230 +1,230 @@ -namespace BinDays.Api.Collectors.Collectors.Councils; - -using BinDays.Api.Collectors.Collectors.Vendors; -using BinDays.Api.Collectors.Models; -using BinDays.Api.Collectors.Utilities; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Text.Json; -using System.Text.RegularExpressions; - -/// -/// Collector implementation for Harborough District Council. -/// -internal sealed partial class HarboroughDistrictCouncil : GovUkCollectorBase, ICollector -{ - /// - public string Name => "Harborough District Council"; - - /// - public Uri WebsiteUrl => new("https://www.harborough.gov.uk/"); - - /// - public override string GovUkId => "harborough"; - - /// - /// The list of bin types for this collector. - /// - private readonly IReadOnlyCollection _binTypes = [ - new() - { - Name = "General Waste", - Colour = BinColour.Black, - Keys = [ "Non-recyclable waste" ], - }, - new() - { - Name = "Mixed Recycling", - Colour = BinColour.Blue, - Keys = [ "Recycling collection" ], - }, - new() - { - Name = "Garden Waste", - Colour = BinColour.Green, - Keys = [ "Garden waste" ], - }, - ]; - - private const string _baseUrl = "http://harborough.fccenvironment.co.uk/"; - private const string _forwardedProtoHeaderValue = "https"; - - /// - /// Regex for the bin days list items. - /// - [GeneratedRegex(@"
  • \s*(?[^<]+?)\s*]*>\s*(?[^<]+)\s*\s*
  • ", RegexOptions.IgnoreCase)] - private static partial Regex BinDaysRegex(); - - /// - /// Regex for the next scheduled bin collection block. - /// - [GeneratedRegex(@"block-your-next-scheduled-bin-collection-days"".*?(?
      .*?
    )", RegexOptions.Singleline)] - private static partial Regex BinDaysSectionRegex(); - - /// - public GetAddressesResponse GetAddresses(string postcode, ClientSideResponse? clientSideResponse) - { - // Prepare client-side request for getting addresses - if (clientSideResponse == null) - { - var requestBody = $$""" - { - "Postcode": "{{postcode}}" - } - """; - - var clientSideRequest = new ClientSideRequest - { - RequestId = 1, - Url = $"{_baseUrl}getAddress", - Method = "POST", - Headers = new() - { - { "user-agent", Constants.UserAgent }, - { "content-type", "application/json" }, - { "x-forwarded-proto", _forwardedProtoHeaderValue }, - }, - Body = requestBody, - Options = new ClientSideOptions - { - FollowRedirects = false, - }, - }; - - var getAddressesResponse = new GetAddressesResponse - { - NextClientSideRequest = clientSideRequest, - }; - - return getAddressesResponse; - } - // Process addresses from response - else if (clientSideResponse.RequestId == 1) - { - using var jsonDocument = JsonDocument.Parse(clientSideResponse.Content); - var addressElements = jsonDocument.RootElement.GetProperty("datas").EnumerateArray(); - - // Iterate through each address, and create a new address object - var addresses = new List
    (); - foreach (var addressElement in addressElements) - { - var uprn = addressElement.GetProperty("AccountSiteUprn").GetString()!; - - if (string.IsNullOrWhiteSpace(uprn)) - { - continue; - } - - var property = addressElement.GetProperty("SiteShortAddress").GetString()!.Trim(); - var addressLabel = addressElement.GetProperty("SiteShortAddressLabel").GetString()!.Trim(); - - // Uid format: "{uprn};{addressLabel}" - var address = new Address - { - Property = property, - Postcode = postcode, - Uid = $"{uprn};{addressLabel}", - }; - - addresses.Add(address); - } - - var getAddressesResponse = new GetAddressesResponse - { - Addresses = [.. addresses], - }; - - return getAddressesResponse; - } - - // Throw exception for invalid request - throw new InvalidOperationException("Invalid client-side request."); - } - - /// - public GetBinDaysResponse GetBinDays(Address address, ClientSideResponse? clientSideResponse) - { - // Prepare client-side request for getting bin days - if (clientSideResponse == null) - { - // Uid format: "{uprn};{addressLabel}" - var addressParts = address.Uid!.Split(';', 2); - var uprn = addressParts[0]; - var addressLabel = addressParts[1]; - - var requestBody = ProcessingUtilities.ConvertDictionaryToFormData(new Dictionary - { - { "Uprn", uprn }, - { "hiddenAddressLabel", addressLabel }, - }); - - var clientSideRequest = new ClientSideRequest - { - RequestId = 1, - Url = $"{_baseUrl}detail-address", - Method = "POST", - Headers = new() - { - { "user-agent", Constants.UserAgent }, - { "content-type", "application/x-www-form-urlencoded; charset=UTF-8" }, - { "x-forwarded-proto", _forwardedProtoHeaderValue }, - }, - Body = requestBody, - Options = new ClientSideOptions - { - FollowRedirects = false, - }, - }; - - var getBinDaysResponse = new GetBinDaysResponse - { - NextClientSideRequest = clientSideRequest, - }; - - return getBinDaysResponse; - } - // Process bin days from response - else if (clientSideResponse.RequestId == 1) - { - var binDaysContent = BinDaysSectionRegex().Match(clientSideResponse.Content).Groups["content"].Value; - var rawBinDays = BinDaysRegex().Matches(binDaysContent)!; - - // Iterate through each bin day, and create a new bin day object - var binDays = new List(); - foreach (Match rawBinDay in rawBinDays) - { - var service = rawBinDay.Groups["service"].Value.Trim(); - var collectionDate = rawBinDay.Groups["date"].Value.Trim(); - - var date = DateOnly.ParseExact( - collectionDate, - "d MMMM yyyy", - CultureInfo.InvariantCulture, - DateTimeStyles.None - ); - - var matchedBins = ProcessingUtilities.GetMatchingBins(_binTypes, service); - - var binDay = new BinDay - { - Date = date, - Address = address, - Bins = matchedBins, - }; - - binDays.Add(binDay); - } - - var getBinDaysResponse = new GetBinDaysResponse - { - BinDays = ProcessingUtilities.ProcessBinDays(binDays), - }; - - return getBinDaysResponse; - } - - // Throw exception for invalid request - throw new InvalidOperationException("Invalid client-side request."); - } -} +namespace BinDays.Api.Collectors.Collectors.Councils; + +using BinDays.Api.Collectors.Collectors.Vendors; +using BinDays.Api.Collectors.Models; +using BinDays.Api.Collectors.Utilities; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text.Json; +using System.Text.RegularExpressions; + +/// +/// Collector implementation for Harborough District Council. +/// +internal sealed partial class HarboroughDistrictCouncil : GovUkCollectorBase, ICollector +{ + /// + public string Name => "Harborough District Council"; + + /// + public Uri WebsiteUrl => new("https://www.harborough.gov.uk/"); + + /// + public override string GovUkId => "harborough"; + + /// + /// The list of bin types for this collector. + /// + private readonly IReadOnlyCollection _binTypes = [ + new() + { + Name = "General Waste", + Colour = BinColour.Black, + Keys = [ "Non-recyclable waste" ], + }, + new() + { + Name = "Mixed Recycling", + Colour = BinColour.Blue, + Keys = [ "Recycling collection" ], + }, + new() + { + Name = "Garden Waste", + Colour = BinColour.Green, + Keys = [ "Garden waste" ], + }, + ]; + + private const string _baseUrl = "http://harborough.fccenvironment.co.uk/"; + private const string _forwardedProtoHeaderValue = "https"; + + /// + /// Regex for the bin days list items. + /// + [GeneratedRegex(@"
  • \s*(?[^<]+?)\s*]*>\s*(?[^<]+)\s*\s*
  • ", RegexOptions.IgnoreCase)] + private static partial Regex BinDaysRegex(); + + /// + /// Regex for the next scheduled bin collection block. + /// + [GeneratedRegex(@"block-your-next-scheduled-bin-collection-days"".*?(?
      .*?
    )", RegexOptions.Singleline)] + private static partial Regex BinDaysSectionRegex(); + + /// + public GetAddressesResponse GetAddresses(string postcode, ClientSideResponse? clientSideResponse) + { + // Prepare client-side request for getting addresses + if (clientSideResponse == null) + { + var requestBody = $$""" + { + "Postcode": "{{postcode}}" + } + """; + + var clientSideRequest = new ClientSideRequest + { + RequestId = 1, + Url = $"{_baseUrl}getAddress", + Method = "POST", + Headers = new() + { + { "user-agent", Constants.UserAgent }, + { "content-type", "application/json" }, + { "x-forwarded-proto", _forwardedProtoHeaderValue }, + }, + Body = requestBody, + Options = new ClientSideOptions + { + FollowRedirects = false, + }, + }; + + var getAddressesResponse = new GetAddressesResponse + { + NextClientSideRequest = clientSideRequest, + }; + + return getAddressesResponse; + } + // Process addresses from response + else if (clientSideResponse.RequestId == 1) + { + using var jsonDocument = JsonDocument.Parse(clientSideResponse.Content); + var addressElements = jsonDocument.RootElement.GetProperty("datas").EnumerateArray(); + + // Iterate through each address, and create a new address object + var addresses = new List
    (); + foreach (var addressElement in addressElements) + { + var uprn = addressElement.GetProperty("AccountSiteUprn").GetString()!; + + if (string.IsNullOrWhiteSpace(uprn)) + { + continue; + } + + var property = addressElement.GetProperty("SiteShortAddress").GetString()!.Trim(); + var addressLabel = addressElement.GetProperty("SiteShortAddressLabel").GetString()!.Trim(); + + // Uid format: "{uprn};{addressLabel}" + var address = new Address + { + Property = property, + Postcode = postcode, + Uid = $"{uprn};{addressLabel}", + }; + + addresses.Add(address); + } + + var getAddressesResponse = new GetAddressesResponse + { + Addresses = [.. addresses], + }; + + return getAddressesResponse; + } + + // Throw exception for invalid request + throw new InvalidOperationException("Invalid client-side request."); + } + + /// + public GetBinDaysResponse GetBinDays(Address address, ClientSideResponse? clientSideResponse) + { + // Prepare client-side request for getting bin days + if (clientSideResponse == null) + { + // Uid format: "{uprn};{addressLabel}" + var addressParts = address.Uid!.Split(';', 2); + var uprn = addressParts[0]; + var addressLabel = addressParts[1]; + + var requestBody = ProcessingUtilities.ConvertDictionaryToFormData(new Dictionary + { + { "Uprn", uprn }, + { "hiddenAddressLabel", addressLabel }, + }); + + var clientSideRequest = new ClientSideRequest + { + RequestId = 1, + Url = $"{_baseUrl}detail-address", + Method = "POST", + Headers = new() + { + { "user-agent", Constants.UserAgent }, + { "content-type", "application/x-www-form-urlencoded; charset=UTF-8" }, + { "x-forwarded-proto", _forwardedProtoHeaderValue }, + }, + Body = requestBody, + Options = new ClientSideOptions + { + FollowRedirects = false, + }, + }; + + var getBinDaysResponse = new GetBinDaysResponse + { + NextClientSideRequest = clientSideRequest, + }; + + return getBinDaysResponse; + } + // Process bin days from response + else if (clientSideResponse.RequestId == 1) + { + var binDaysContent = BinDaysSectionRegex().Match(clientSideResponse.Content).Groups["content"].Value; + var rawBinDays = BinDaysRegex().Matches(binDaysContent)!; + + // Iterate through each bin day, and create a new bin day object + var binDays = new List(); + foreach (Match rawBinDay in rawBinDays) + { + var service = rawBinDay.Groups["service"].Value.Trim(); + var collectionDate = rawBinDay.Groups["date"].Value.Trim(); + + var date = DateOnly.ParseExact( + collectionDate, + "d MMMM yyyy", + CultureInfo.InvariantCulture, + DateTimeStyles.None + ); + + var matchedBins = ProcessingUtilities.GetMatchingBins(_binTypes, service); + + var binDay = new BinDay + { + Date = date, + Address = address, + Bins = matchedBins, + }; + + binDays.Add(binDay); + } + + var getBinDaysResponse = new GetBinDaysResponse + { + BinDays = ProcessingUtilities.ProcessBinDays(binDays), + }; + + return getBinDaysResponse; + } + + // Throw exception for invalid request + throw new InvalidOperationException("Invalid client-side request."); + } +} diff --git a/BinDays.Api.IntegrationTests/Collectors/Councils/HarboroughDistrictCouncilTests.cs b/BinDays.Api.IntegrationTests/Collectors/Councils/HarboroughDistrictCouncilTests.cs index a8cdda1..3bea48f 100644 --- a/BinDays.Api.IntegrationTests/Collectors/Councils/HarboroughDistrictCouncilTests.cs +++ b/BinDays.Api.IntegrationTests/Collectors/Councils/HarboroughDistrictCouncilTests.cs @@ -1,32 +1,32 @@ -namespace BinDays.Api.IntegrationTests.Collectors.Councils; - -using BinDays.Api.Collectors.Collectors.Councils; -using BinDays.Api.IntegrationTests.Helpers; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -public class HarboroughDistrictCouncilTests -{ - private readonly IntegrationTestClient _client; - private readonly ITestOutputHelper _outputHelper; - private static readonly string _govUkId = new HarboroughDistrictCouncil().GovUkId; - - public HarboroughDistrictCouncilTests(ITestOutputHelper outputHelper) - { - _outputHelper = outputHelper; - _client = new IntegrationTestClient(outputHelper); - } - - [Theory] - [InlineData("LE17 5EG")] - public async Task GetBinDaysTest(string postcode) - { - await TestSteps.EndToEnd( - _client, - postcode, - _govUkId, - _outputHelper - ); - } -} +namespace BinDays.Api.IntegrationTests.Collectors.Councils; + +using BinDays.Api.Collectors.Collectors.Councils; +using BinDays.Api.IntegrationTests.Helpers; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +public class HarboroughDistrictCouncilTests +{ + private readonly IntegrationTestClient _client; + private readonly ITestOutputHelper _outputHelper; + private static readonly string _govUkId = new HarboroughDistrictCouncil().GovUkId; + + public HarboroughDistrictCouncilTests(ITestOutputHelper outputHelper) + { + _outputHelper = outputHelper; + _client = new IntegrationTestClient(outputHelper); + } + + [Theory] + [InlineData("LE17 5EG")] + public async Task GetBinDaysTest(string postcode) + { + await TestSteps.EndToEnd( + _client, + postcode, + _govUkId, + _outputHelper + ); + } +} From 7b554f091b23fc2dd2e6c7ae4736d46978754dce Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Sun, 22 Feb 2026 11:26:24 +0000 Subject: [PATCH 3/3] Fix PR review comments for HarboroughDistrictCouncil collector - Fix _baseUrl from http to https (security) - Replace JSON string interpolation with JsonSerializer.Serialize to prevent injection - Fix collection expression bracket formatting - Use target-typed new() for Dictionary initialization - Add summary docstrings to private const fields Co-authored-by: Andrew Riggs --- .../Councils/HarboroughDistrictCouncil.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs b/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs index b4b8f5e..95c503b 100644 --- a/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs +++ b/BinDays.Api.Collectors/Collectors/Councils/HarboroughDistrictCouncil.cs @@ -26,7 +26,8 @@ internal sealed partial class HarboroughDistrictCouncil : GovUkCollectorBase, IC /// /// The list of bin types for this collector. /// - private readonly IReadOnlyCollection _binTypes = [ + private readonly IReadOnlyCollection _binTypes = + [ new() { Name = "General Waste", @@ -47,7 +48,14 @@ internal sealed partial class HarboroughDistrictCouncil : GovUkCollectorBase, IC }, ]; - private const string _baseUrl = "http://harborough.fccenvironment.co.uk/"; + /// + /// The base URL for the FCC Environment API. + /// + private const string _baseUrl = "https://harborough.fccenvironment.co.uk/"; + + /// + /// The value for the x-forwarded-proto header. + /// private const string _forwardedProtoHeaderValue = "https"; /// @@ -68,11 +76,7 @@ public GetAddressesResponse GetAddresses(string postcode, ClientSideResponse? cl // Prepare client-side request for getting addresses if (clientSideResponse == null) { - var requestBody = $$""" - { - "Postcode": "{{postcode}}" - } - """; + var requestBody = JsonSerializer.Serialize(new { Postcode = postcode }); var clientSideRequest = new ClientSideRequest { @@ -153,7 +157,7 @@ public GetBinDaysResponse GetBinDays(Address address, ClientSideResponse? client var uprn = addressParts[0]; var addressLabel = addressParts[1]; - var requestBody = ProcessingUtilities.ConvertDictionaryToFormData(new Dictionary + var requestBody = ProcessingUtilities.ConvertDictionaryToFormData(new() { { "Uprn", uprn }, { "hiddenAddressLabel", addressLabel },