From b0a8085ea0c5a508ecd9c50916926f2a6c1ef289 Mon Sep 17 00:00:00 2001 From: Keir Date: Sun, 22 Oct 2023 14:57:39 +0100 Subject: [PATCH] New Source: Adur & Worthing Councils Bin Days (#1336) * feat: add adur & worthing councils bin day * reformatting --- .pre-commit-config.yaml | 2 +- README.md | 1 + .../source/adur_worthing_gov_uk.py | 73 +++++++++++++++++++ doc/source/adur_worthing_gov_uk.md | 32 ++++++++ 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 custom_components/waste_collection_schedule/waste_collection_schedule/source/adur_worthing_gov_uk.py create mode 100644 doc/source/adur_worthing_gov_uk.md diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6098eeb6f..82e5c82dc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: hooks: - id: codespell args: - - --ignore-words-list=hass,alot,datas,dof,dur,farenheit,hist,iff,ines,ist,lightsensor,mut,nd,pres,referer,ser,serie,te,technik,ue,uint,visability,wan,wanna,withing,Adresse,termine,adresse,oder,alle,assistent,hart,marz + - --ignore-words-list=hass,alot,datas,dof,dur,farenheit,hist,iff,ines,ist,lightsensor,mut,nd,pres,referer,ser,serie,te,technik,ue,uint,visability,wan,wanna,withing,Adresse,termine,adresse,oder,alle,assistent,hart,marz,worthing - --skip="./.*,*.csv,*.json" - --quiet-level=2 exclude_types: [csv, json] diff --git a/README.md b/README.md index da1050659..1a7ad7b9a 100644 --- a/README.md +++ b/README.md @@ -965,6 +965,7 @@ Waste collection schedules in the following formats and countries are supported. United Kingdom - [Aberdeenshire Council](/doc/source/aberdeenshire_gov_uk.md) / aberdeenshire.gov.uk +- [Adur & Worthing Councils](/doc/source/adur_worthing_gov_uk.md) / adur-worthing.gov.uk - [Allerdale Borough Council](/doc/source/allerdale_gov_uk.md) / allerdale.gov.uk - [Amber Valley Borough Council](/doc/source/ambervalley_gov_uk.md) / ambervalley.gov.uk - [Ashfield District Council](/doc/source/ashfield_gov_uk.md) / ashfield.gov.uk diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/adur_worthing_gov_uk.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/adur_worthing_gov_uk.py new file mode 100644 index 000000000..b4aeb6a87 --- /dev/null +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/adur_worthing_gov_uk.py @@ -0,0 +1,73 @@ +from datetime import datetime + +import bs4 +import requests +from waste_collection_schedule import Collection # type: ignore[attr-defined] + +TITLE = "Adur & Worthing Councils" +DESCRIPTION = "Source for adur-worthing.gov.uk services for Adur & Worthing, UK." +URL = "https://adur-worthing.gov.uk" +TEST_CASES = { + "Test_001": {"postcode": "BN15 9UX", "address": "1 Western Road North"}, + "Test_002": {"postcode": "BN43 5WE", "address": "6 Hebe Road"}, +} +HEADERS = { + "user-agent": "Mozilla/5.0", +} +ICON_MAP = { + "Recycling": "mdi:recycle", + "Refuse": "mdi:trash-can", + "Garden": "mdi:leaf", +} + + +class Source: + def __init__(self, postcode, address): + self._postcode = postcode + self._address = address + + def fetch(self): + + if self._postcode is None or self._address is None: + raise ValueError("Either postcode or address is None") + + s = requests.Session() + + postcode_search_request = s.get( + f"https://www.adur-worthing.gov.uk/bin-day/?brlu-address-postcode={self._postcode}&return-url=/bin-day/&action=search", + headers=HEADERS, + ) + html_addresses = postcode_search_request.content + addresses = bs4.BeautifulSoup(html_addresses, "html.parser") + addresses_select = addresses.find("select", {"id": "brlu-selected-address"}) + + found_address = None + for address in addresses_select.find_all("option"): + if self._address in address.get_text(): + found_address = address + + if found_address is None: + raise ValueError("Address not found") + + collections_request = s.get( + f"https://www.adur-worthing.gov.uk/bin-day/?brlu-selected-address={address['value']}&return-url=/bin-day/", + headers=HEADERS, + ) + html_collections = collections_request.content + bin_collections = bs4.BeautifulSoup(html_collections, "html.parser") + + bin_days_table = bin_collections.find("table", class_="bin-days") + bin_days_table_body = bin_days_table.find("tbody") + bin_days_by_type = bin_days_table_body.find_all("tr") + + entries = [] + + for bin_by_type in bin_days_by_type: + bin_type = bin_by_type.find("th").text + icon = ICON_MAP.get(bin_type) + bin_days = bin_by_type.find_all("td")[-1].get_text(separator="\n") + for bin_day in bin_days.split("\n"): + bin_datetime = datetime.strptime(bin_day, "%A %d %b %Y").date() + entries.append(Collection(t=bin_type, date=bin_datetime, icon=icon)) + + return entries diff --git a/doc/source/adur_worthing_gov_uk.md b/doc/source/adur_worthing_gov_uk.md new file mode 100644 index 000000000..6215f667c --- /dev/null +++ b/doc/source/adur_worthing_gov_uk.md @@ -0,0 +1,32 @@ +# Adur & Worthing Councils + +Support for schedules provided by [Adur & Worthing Councils](https://www.adur-worthing.gov.uk/bin-day/), UK. + +## Configuration via configuration.yaml + +```yaml +waste_collection_schedule: + sources: + - name: adur_worthing_gov_uk + args: + postcode: POSTCODE + address: FIRST LINE OF ADDRESS (X, STREET NAME) +``` + +### Configuration Variables + +**postcode** +*(string) (required)* +**address** +*(string) (required)* + +## Example + +```yaml +waste_collection_schedule: + sources: + - name: adur_worthing_gov_uk + args: + postcode: BN15 9UX + address: 1 Western Road +```