diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/goldcoast_qld_gov_au.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/goldcoast_qld_gov_au.py index 3e049df64..72d93dd6c 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/goldcoast_qld_gov_au.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/goldcoast_qld_gov_au.py @@ -1,78 +1,79 @@ -import logging -import re -from datetime import datetime - -import requests -from bs4 import BeautifulSoup -from waste_collection_schedule import Collection # type: ignore[attr-defined] - -TITLE = "Gold Coast City Council" -DESCRIPTION = "Source for Gold Coast Council rubbish collection." -URL = "https://www.goldcoast.qld.gov.au" -TEST_CASES = { - "MovieWorx": { "street_address": "50 Millaroo Dr Helensvale" }, - "The Henchman": { "street_address": "6/8 Henchman Ave Miami" }, - "Pie Pie": { "street_address": "1887 Gold Coast Hwy Burleigh Heads" } -} - -_LOGGER = logging.getLogger(__name__) - -ICON_MAP = { # Dict of waste types and suitable mdi icons - "General waste": "mdi:trash-can", - "Recycling": "mdi:recycle", - "Green organics": "mdi:leaf", -} - -class Source: - def __init__(self, street_address): - self._street_address = street_address - - def fetch(self): - session = requests.Session() - - # Making a get request - response = session.get( - "https://www.goldcoast.qld.gov.au/api/v1/myarea/searchfuzzy?maxresults=1", - params={"keywords": self._street_address}, - ) - response.raise_for_status() - addressSearchApiResults = response.json() - if ( - addressSearchApiResults["Items"] is None - or len(addressSearchApiResults["Items"]) < 1 - ): - raise Exception( - f"Address search for '{self._street_address}' returned no results. Check your address on https://www.goldcoast.qld.gov.au/Services/Waste-recycling/Find-my-bin-day" - ) - - addressSearchTopHit = addressSearchApiResults["Items"][0] - _LOGGER.debug("Address search top hit: %s", addressSearchTopHit) - - geolocationid = addressSearchTopHit["Id"] - _LOGGER.debug("Geolocationid: %s", geolocationid) - - response = session.get( - "Https://www.goldcoast.qld.gov.au/ocapi/Public/myarea/wasteservices?ocsvclang=en-AU", - params={"geolocationid": geolocationid}, - ) - response.raise_for_status() - - wasteApiResult = response.json() - _LOGGER.debug("Waste API result: %s", wasteApiResult) - - soup = BeautifulSoup(wasteApiResult["responseContent"], "html.parser") - - entries = [] - for article in soup.find_all("article"): - waste_type = article.h3.string - icon = ICON_MAP.get(waste_type, "mdi:trash-can") - next_pickup = article.find(class_="next-service").string.strip() - if re.match(r"[^\s]* \d{1,2}\/\d{1,2}\/\d{4}", next_pickup): - next_pickup_date = datetime.strptime( - next_pickup.split(sep=" ")[1], "%d/%m/%Y" - ).date() - entries.append( - Collection(date=next_pickup_date, t=waste_type, icon=icon) - ) - - return entries +import logging +import re +from datetime import datetime + +import requests +from bs4 import BeautifulSoup +from waste_collection_schedule import Collection # type: ignore[attr-defined] + +TITLE = "Gold Coast City Council" +DESCRIPTION = "Source for Gold Coast Council rubbish collection." +URL = "https://www.goldcoast.qld.gov.au" +TEST_CASES = { + "MovieWorx": {"street_address": "50 Millaroo Dr Helensvale"}, + "The Henchman": {"street_address": "6/8 Henchman Ave Miami"}, + "Pie Pie": {"street_address": "1887 Gold Coast Hwy Burleigh Heads"}, +} + +_LOGGER = logging.getLogger(__name__) + +ICON_MAP = { # Dict of waste types and suitable mdi icons + "General waste": "mdi:trash-can", + "Recycling": "mdi:recycle", + "Green organics": "mdi:leaf", +} + + +class Source: + def __init__(self, street_address): + self._street_address = street_address + + def fetch(self): + session = requests.Session() + + # Making a get request + response = session.get( + "https://www.goldcoast.qld.gov.au/api/v1/myarea/searchfuzzy?maxresults=1", + params={"keywords": self._street_address}, + ) + response.raise_for_status() + addressSearchApiResults = response.json() + if ( + addressSearchApiResults["Items"] is None + or len(addressSearchApiResults["Items"]) < 1 + ): + raise Exception( + f"Address search for '{self._street_address}' returned no results. Check your address on https://www.goldcoast.qld.gov.au/Services/Waste-recycling/Find-my-bin-day" + ) + + addressSearchTopHit = addressSearchApiResults["Items"][0] + _LOGGER.debug("Address search top hit: %s", addressSearchTopHit) + + geolocationid = addressSearchTopHit["Id"] + _LOGGER.debug("Geolocationid: %s", geolocationid) + + response = session.get( + "Https://www.goldcoast.qld.gov.au/ocapi/Public/myarea/wasteservices?ocsvclang=en-AU", + params={"geolocationid": geolocationid}, + ) + response.raise_for_status() + + wasteApiResult = response.json() + _LOGGER.debug("Waste API result: %s", wasteApiResult) + + soup = BeautifulSoup(wasteApiResult["responseContent"], "html.parser") + + entries = [] + for article in soup.find_all("article"): + waste_type = article.h3.string + icon = ICON_MAP.get(waste_type, "mdi:trash-can") + next_pickup = article.find(class_="next-service").string.strip() + if re.match(r"[^\s]* \d{1,2}\/\d{1,2}\/\d{4}", next_pickup): + next_pickup_date = datetime.strptime( + next_pickup.split(sep=" ")[1], "%d/%m/%Y" + ).date() + entries.append( + Collection(date=next_pickup_date, t=waste_type, icon=icon) + ) + + return entries diff --git a/doc/source/abfallwirtschaft_fuerth_eu.md b/doc/source/abfallwirtschaft_fuerth_eu.md index ca814c3d7..b2ccff3f3 100644 --- a/doc/source/abfallwirtschaft_fuerth_eu.md +++ b/doc/source/abfallwirtschaft_fuerth_eu.md @@ -1,55 +1,55 @@ -# Abfuhrkalender Stadt Fürth - -Support for schedules provided by . - -## Configuration via configuration.yaml - -```yaml -waste_collection_schedule: - sources: - - name: abfallwirtschaft_fuerth_eu - args: - id: ID -``` - -### Configuration Variables - -**id** -_(integer) (required)_ : The unique 8-digit identifier of your street section - -## Example Configuration - -```yaml -waste_collection_schedule: - sources: - - name: abfallwirtschaft_fuerth_eu - args: - id: 96983001 -``` - -## Example Sensor -```yaml - - platform: waste_collection_schedule - name: waste_restabfall - details_format: "upcoming" - value_template: '{{ value.daysTo }}' - types: - - Restabfall -``` - -## How to get the source arguments - -1. Open . -2. Fill out the filter fields on the page (street and number). -3. click the button "Abfuhrtermine importieren" and right click on "Kalender-Datei herunterladen" selecting "Copy link address". You should get something like this `https://abfallwirtschaft.fuerth.eu/termine.php?icalexport=96983001` -4. Copy the id number at the end of the link to your configuration file. - -## Adding Sensors -```yaml - - platform: waste_collection_schedule - name: waste_restabfall - details_format: "upcoming" - value_template: '{{ value.daysTo }}' - types: - - Restabfall +# Abfuhrkalender Stadt Fürth + +Support for schedules provided by . + +## Configuration via configuration.yaml + +```yaml +waste_collection_schedule: + sources: + - name: abfallwirtschaft_fuerth_eu + args: + id: ID +``` + +### Configuration Variables + +**id** +_(integer) (required)_ : The unique 8-digit identifier of your street section + +## Example Configuration + +```yaml +waste_collection_schedule: + sources: + - name: abfallwirtschaft_fuerth_eu + args: + id: 96983001 +``` + +## Example Sensor +```yaml + - platform: waste_collection_schedule + name: waste_restabfall + details_format: "upcoming" + value_template: '{{ value.daysTo }}' + types: + - Restabfall +``` + +## How to get the source arguments + +1. Open . +2. Fill out the filter fields on the page (street and number). +3. click the button "Abfuhrtermine importieren" and right click on "Kalender-Datei herunterladen" selecting "Copy link address". You should get something like this `https://abfallwirtschaft.fuerth.eu/termine.php?icalexport=96983001` +4. Copy the id number at the end of the link to your configuration file. + +## Adding Sensors +```yaml + - platform: waste_collection_schedule + name: waste_restabfall + details_format: "upcoming" + value_template: '{{ value.daysTo }}' + types: + - Restabfall ``` \ No newline at end of file diff --git a/doc/source/belmont_wa_gov_au.md b/doc/source/belmont_wa_gov_au.md index 1f807c085..9d551d182 100644 --- a/doc/source/belmont_wa_gov_au.md +++ b/doc/source/belmont_wa_gov_au.md @@ -1,32 +1,32 @@ -# Belmont City Council - -Support for schedules provided by [Belmont City Council Waste and Recycling](https://www.belmont.wa.gov.au/live/at-your-place/bins,-waste-and-recycling). - -## Configuration via configuration.yaml - -```yaml -waste_collection_schedule: - sources: - - name: belmont_wa_gov_au - args: - address: ADDRESS -``` - -### Configuration Variables - -**address** -*(string) (required)* - -## Example - -```yaml -waste_collection_schedule: - sources: - - name: belmont_wa_gov_au - args: - address: 196 Abernethy Road Belmont 6104 -``` - -## How to get the source arguments - -Visit the [Belmont City Council Waste and Recycling](https://www.belmont.wa.gov.au/live/at-your-place/bins,-waste-and-recycling) page and search for your address. The arguments should exactly match the results of the property. +# Belmont City Council + +Support for schedules provided by [Belmont City Council Waste and Recycling](https://www.belmont.wa.gov.au/live/at-your-place/bins,-waste-and-recycling). + +## Configuration via configuration.yaml + +```yaml +waste_collection_schedule: + sources: + - name: belmont_wa_gov_au + args: + address: ADDRESS +``` + +### Configuration Variables + +**address** +*(string) (required)* + +## Example + +```yaml +waste_collection_schedule: + sources: + - name: belmont_wa_gov_au + args: + address: 196 Abernethy Road Belmont 6104 +``` + +## How to get the source arguments + +Visit the [Belmont City Council Waste and Recycling](https://www.belmont.wa.gov.au/live/at-your-place/bins,-waste-and-recycling) page and search for your address. The arguments should exactly match the results of the property.