From c7bfad5761daee021c375d79da8f97fea53d884b Mon Sep 17 00:00:00 2001 From: 5ila5 <5ila5@users.noreply.github.com> Date: Mon, 22 Jul 2024 21:18:59 +0200 Subject: [PATCH] add lots of custom translations for german sources --- .../source/ahk_heidekreis_de.py | 9 + .../source/art_trier_de.py | 7 + .../source/asr_chemnitz_de.py | 47 +++-- .../source/awb_emsland_de.py | 10 + .../source/awb_oldenburg_de.py | 8 + .../source/awbkoeln_de.py | 8 + .../source/awlneuss_de.py | 9 + .../source/awn_de.py | 14 +- .../source/awr_de.py | 7 + .../source/awsh_de.py | 7 + .../source/berlin_recycling_de.py | 28 ++- .../source/bielefeld_de.py | 9 + .../source/bsr_de.py | 8 + .../source/buergerportal_de.py | 11 + .../source/c_trace_de.py | 12 ++ .../source/cederbaum_de.py | 6 + .../source/dillingen_saar_de.py | 7 +- .../source/ead_darmstadt_de.py | 6 + .../source/egn_abfallkalender_de.py | 9 + .../eigenbetrieb_abfallwirtschaft_de.py | 6 + .../source/erlangen_hoechstadt_de.py | 8 + .../source/geoport_nwm_de.py | 7 + .../source/hausmuell_info.py | 18 ++ .../source/heilbronn_de.py | 13 ++ .../waste_collection_schedule/source/ics.py | 18 ++ .../source/infeo_at.py | 11 + .../source/insert_it_de.py | 64 +++--- .../source/jumomind_de.py | 11 + .../source/karlsruhe_de.py | 14 ++ .../source/korneuburg_stadtservice_at.py | 19 +- .../source/ks_boerde_de.py | 15 +- .../source/kwb_goslar_de.py | 10 + .../source/kwu_de.py | 9 + .../source/landkreis_rhoen_grabfeld.py | 40 ++-- .../source/landkreis_wittmund_de.py | 69 +++---- .../source/lindau_ch.py | 6 + .../source/lrasha_de.py | 11 +- .../source/mags_de.py | 43 ++-- .../source/meinawb_de.py | 9 + .../source/monaloga_de.py | 12 ++ .../source/muellabfuhr_de.py | 9 + .../source/muellmax_de.py | 9 + .../source/muenchenstein_ch.py | 7 + .../source/multiple.py | 7 + .../source/offenbach_de.py | 6 + .../source/potsdam_de.py | 191 +++++++++++++++--- .../source/real_luzern_ch.py | 8 + .../source/regioentsorgung_de.py | 9 + .../source/rh_entsorgung_de.py | 13 +- .../source/sbazv_de.py | 8 + .../source/sector27_de.py | 7 + .../source/stuttgart_de.py | 8 + .../source/tbv_velbert_de.py | 6 + .../source/tonnenleerung_de.py | 6 + .../source/umweltverbaende_at.py | 10 + .../source/was_wolfsburg_de.py | 7 + .../source/wermelskirchen_de.py | 8 + .../source/wsz_moosburg_at.py | 19 +- .../source/wuerzburg_de.py | 12 +- .../source/zakb_de.py | 27 ++- .../source/zva_sek_de.py | 71 ++++--- .../source/zva_wmk_de.py | 7 + update_docu_links.py | 21 +- 63 files changed, 898 insertions(+), 213 deletions(-) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/ahk_heidekreis_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/ahk_heidekreis_de.py index 9cef2811..5431e9d8 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/ahk_heidekreis_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/ahk_heidekreis_de.py @@ -26,6 +26,15 @@ TEST_CASES = { }, } +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + "postcode": "PLZ", + "house_number": "Hausnummer", + } +} + class Source: def __init__(self, city, postcode, street, house_number): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/art_trier_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/art_trier_de.py index 5cb72bbf..999b5a7a 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/art_trier_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/art_trier_de.py @@ -56,6 +56,13 @@ SPECIAL_CHARS = str.maketrans( ) LOGGER = logging.getLogger(__name__) +PARAM_TRANSLATIONS = { + "de": { + "zip_code": "PLZ", + "district": "Ort", + } +} + class Source: def __init__(self, district: str, zip_code: str): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/asr_chemnitz_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/asr_chemnitz_de.py index d7a10e9f..688ec99d 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/asr_chemnitz_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/asr_chemnitz_de.py @@ -1,16 +1,27 @@ import requests +from bs4 import BeautifulSoup from waste_collection_schedule import Collection # type: ignore[attr-defined] from waste_collection_schedule.service.ICS import ICS -from bs4 import BeautifulSoup TITLE = "ASR Stadt Chemnitz" DESCRIPTION = "Source for ASR Stadt Chemnitz." URL = "https://www.asr-chemnitz.de" TEST_CASES = { "Hübschmannstr. 4": {"street": "Hübschmannstr.", "house_number": "4"}, - "Carl-von-Ossietzky-Str 94": {"street": "Carl-von-Ossietzky-Str", "house_number": 94}, - "Wasserscheide 5 (2204101)": {"street": "Wasserscheide", "house_number": "5", "object_number": "2204101"}, - "Wasserscheide 5 (89251)": {"street": "Wasserscheide", "house_number": "5", "object_number": 89251}, + "Carl-von-Ossietzky-Str 94": { + "street": "Carl-von-Ossietzky-Str", + "house_number": 94, + }, + "Wasserscheide 5 (2204101)": { + "street": "Wasserscheide", + "house_number": "5", + "object_number": "2204101", + }, + "Wasserscheide 5 (89251)": { + "street": "Wasserscheide", + "house_number": "5", + "object_number": 89251, + }, "Damaschkestraße 36": {"street": "Damaschkestr.", "house_number": "36"}, } @@ -26,8 +37,19 @@ ICON_MAP = { API_URL = "https://asc.hausmuell.info/ics/ics.php" +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + "house_number": "Hausnummer", + "object_number": "Objektnummer", + } +} + + class Source: - def __init__(self, street: str, house_number: str | int, object_number: str | int = ""): + def __init__( + self, street: str, house_number: str | int, object_number: str | int = "" + ): self._street: str = street self._house_number: str = str(house_number) self._object_number: str = str(object_number) @@ -55,23 +77,21 @@ class Source: r = requests.post("https://asc.hausmuell.info/proxy.php", data=args) r.raise_for_status() - + soup = BeautifulSoup(r.text, "html.parser") street_id = soup.find("span").text.strip() egebiet_id = soup.find_all("span")[1].text.strip() - - + if egebiet_id == "0": if self._object_number == "": raise Exception("No object number provided but needed") args["input"] = self._object_number - args["url"] = 7 + args["url"] = 7 r = requests.post("https://asc.hausmuell.info/proxy.php", data=args) - r.raise_for_status() + r.raise_for_status() soup = BeautifulSoup(r.text, "html.parser") egebiet_id = soup.find_all("span")[1].text.strip() - - + # get dates args = { "input_str": self._street, @@ -104,7 +124,6 @@ class Source: for d in dates: bin_type = d[1].replace("Entsorgung:", "").strip() - entries.append(Collection( - d[0], bin_type, ICON_MAP.get(bin_type))) + entries.append(Collection(d[0], bin_type, ICON_MAP.get(bin_type))) return entries diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awb_emsland_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awb_emsland_de.py index 2e2df9c7..c048d291 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awb_emsland_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awb_emsland_de.py @@ -54,6 +54,16 @@ class HiddenInputParser(HTMLParser): self._args[d["name"]] = d["value"] if "value" in d else "" +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + "house_number": "Hausnummer", + "address_suffix": "Hausnummerzusatz", + } +} + + class Source: def __init__( self, city: str, street: str, house_number: int, address_suffix: str = "" diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awb_oldenburg_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awb_oldenburg_de.py index 70e22b7d..fafd363d 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awb_oldenburg_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awb_oldenburg_de.py @@ -19,6 +19,14 @@ API_URL = "https://www.oldenburg.de/startseite/leben-umwelt/awb/awb-von-a-bis-z/ _LOGGER = logging.getLogger(__name__) +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + "house_number": "Hausnummer", + } +} + + class Source: def __init__(self, street, house_number): self._street = street diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awbkoeln_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awbkoeln_de.py index 6c771264..3f1921b7 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awbkoeln_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awbkoeln_de.py @@ -10,6 +10,14 @@ URL = "https://www.awbkoeln.de" TEST_CASES = {"Koeln": {"street_code": 2, "building_number": 50}} +PARAM_TRANSLATIONS = { + "de": { + "street_code": "Straßencode", + "building_number": "Hausnummer", + } +} + + class Source: def __init__(self, street_code, building_number): self._street_code = street_code diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awlneuss_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awlneuss_de.py index 34dd220c..328f8510 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awlneuss_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awlneuss_de.py @@ -33,6 +33,15 @@ ICON_MAP = { } +PARAM_TRANSLATIONS = { + "de": { + "building_number": "Hausnummer", + "street_name": "Straßenname", + "street_code": "Straßencode", + } +} + + class Source: def __init__( self, diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awn_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awn_de.py index abc371cb..f5f02e86 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awn_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awn_de.py @@ -1,7 +1,7 @@ -import requests -import urllib3 from html.parser import HTMLParser +import requests +import urllib3 from waste_collection_schedule import Collection # type: ignore[attr-defined] from waste_collection_schedule.service.ICS import ICS @@ -39,6 +39,16 @@ SERVLET = ( "https://athos.awn-online.de/WasteManagementNeckarOdenwald/WasteManagementServlet" ) +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + "house_number": "Hausnummer", + "address_suffix": "Hausnummerzusatz", + } +} + + # Parser for HTML input (hidden) text class HiddenInputParser(HTMLParser): def __init__(self): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awr_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awr_de.py index 363db3fb..a0c5a019 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awr_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awr_de.py @@ -13,6 +13,13 @@ TEST_CASES = { _LOGGER = logging.getLogger(__name__) +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + } +} + class Source: def __init__(self, city, street): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awsh_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awsh_de.py index e82ec0e6..67a12e26 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/awsh_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/awsh_de.py @@ -13,6 +13,13 @@ TEST_CASES = { _LOGGER = logging.getLogger(__name__) +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + } +} + class Source: def __init__(self, city, street): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/berlin_recycling_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/berlin_recycling_de.py index 30ee30c5..c5fa2668 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/berlin_recycling_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/berlin_recycling_de.py @@ -17,6 +17,14 @@ TEST_CASES = { SERVICE_URL = "https://kundenportal.berlin-recycling.de/" +PARAM_TRANSLATIONS = { + "de": { + "username": "Benutzername", + "password": "Passwort", + } +} + + class Source: def __init__(self, username, password): self._username = username @@ -44,13 +52,13 @@ class Source: serviceUrl = f"{SERVICE_URL}Default.aspx" # get the default view (might not needed, but is a good check the login worked) - response = session.get('https://kundenportal.berlin-recycling.de/Default.aspx') + response = session.get("https://kundenportal.berlin-recycling.de/Default.aspx") if response.history: - raise Exception ('The default view request was redirected to ' + response.url) - - headers = { - 'Content-Type': 'application/json' - } + raise Exception( + "The default view request was redirected to " + response.url + ) + + headers = {"Content-Type": "application/json"} r = session.post(f"{serviceUrl}/GetDashboard", headers=headers) r.raise_for_status() @@ -63,9 +71,11 @@ class Source: "ordername": "", "orderdir": "", "ClientParameters": "", - "headrecid": "" + "headrecid": "", } - r = session.post(f"{serviceUrl}/GetDatasetTableHead", json=request_data, headers=headers) + r = session.post( + f"{serviceUrl}/GetDatasetTableHead", json=request_data, headers=headers + ) data = json.loads(r.text) # load json again, because response is double coded @@ -74,7 +84,7 @@ class Source: entries = [] if "Object" not in data or "data" not in data["Object"]: raise Exception("No data found", data) - + for d in data["Object"]["data"]: date = datetime.strptime(d["Task Date"], "%Y-%m-%d").date() entries.append(Collection(date, d["Material Description"])) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/bielefeld_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/bielefeld_de.py index 1f7ec025..a5cf1b4f 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/bielefeld_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/bielefeld_de.py @@ -68,6 +68,15 @@ class HiddenInputParser(HTMLParser): self._radio_args = new_radio +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + "house_number": "Hausnummer", + "address_suffix": "Hausnummerzusatz", + } +} + + class Source: def __init__(self, street: str, house_number: int, address_suffix: str = ""): self._street = street diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/bsr_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/bsr_de.py index 28a250c3..285e5b80 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/bsr_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/bsr_de.py @@ -81,6 +81,14 @@ def downloadChristmastreeICS(s, abf_strasse, abf_hausnr): return r.text +PARAM_TRANSLATIONS = { + "de": { + "abf_strasse": "Straße", + "abf_hausnr": "Hausnummer", + } +} + + class Source: def __init__(self, abf_strasse, abf_hausnr): self._abf_strasse = abf_strasse diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/buergerportal_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/buergerportal_de.py index 8ad3b86b..10b7bca2 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/buergerportal_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/buergerportal_de.py @@ -92,6 +92,17 @@ SERVICE_MAP = [ }, ] +PARAM_TRANSLATIONS = { + "de": { + "operator": "Betreiber", + "district": "Ort", + "street": "Straße", + "subdistrict": "Ortsteil", + "number": "Hausnummer", + "show_volume": "Große Container anzeigen", + } +} + # This datalcass is used for adding entries to a set and remove duplicate entries. # The default `Collection` extends the standard dict and thus is not hashable. diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/c_trace_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/c_trace_de.py index 26e0d02f..3082af5b 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/c_trace_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/c_trace_de.py @@ -158,6 +158,18 @@ SERVICE_MAP = { BASE_URL = "https://{subdomain}.c-trace.de" +PARAM_TRANSLATIONS = { + "en": { + "strasse": "Street", + "hausnummer": "House number", + "gemeinde": "Municipality", + "ort": "District", + "ortsteil": "Subdistrict", + "service": "Operator", + } +} + + class Source: def __init__( self, diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/cederbaum_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/cederbaum_de.py index 7722c225..ee342211 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/cederbaum_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/cederbaum_de.py @@ -20,6 +20,12 @@ ICON_MAP = { "PAPER": "mdi:newspaper", } +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + } +} + class Source: def __init__(self, street): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/dillingen_saar_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/dillingen_saar_de.py index 87f0812e..965f574e 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/dillingen_saar_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/dillingen_saar_de.py @@ -33,6 +33,12 @@ ICON_MAP = { "Gelbesäcke Abholung": "mdi:recycle", } +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + } +} + class Source: def __init__(self, street: str): @@ -40,7 +46,6 @@ class Source: self._ics = ICS() def fetch(self): - # the url contains the current year, but this doesn't really seems to matter at least for the ical, since the result is always the same # still replace it for compatibility sake now = datetime.now() diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/ead_darmstadt_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/ead_darmstadt_de.py index 017d8be7..c9dd5608 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/ead_darmstadt_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/ead_darmstadt_de.py @@ -25,6 +25,12 @@ ICON_MAP = { # Optional: Dict of waste types and suitable mdi icons "PPK": "mdi:package-variant", } +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + } +} + class Source: def __init__( diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/egn_abfallkalender_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/egn_abfallkalender_de.py index 7a1561c9..a6d63c84 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/egn_abfallkalender_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/egn_abfallkalender_de.py @@ -39,6 +39,15 @@ ICON_MAP = { "Braun": "mdi:leaf", } +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "district": "Ortsteil", + "street": "Straße", + "housenumber": "Hausnummer", + } +} + class Source: def __init__(self, city, district, street, housenumber): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/eigenbetrieb_abfallwirtschaft_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/eigenbetrieb_abfallwirtschaft_de.py index c4c9ac6d..3de1ba81 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/eigenbetrieb_abfallwirtschaft_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/eigenbetrieb_abfallwirtschaft_de.py @@ -23,6 +23,12 @@ ICON_MAP = { "Papiercontainer": "mdi:package-variant", "Gelbe(r) Sack/Tonne": "mdi:recycle", } +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + } +} class Source: diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/erlangen_hoechstadt_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/erlangen_hoechstadt_de.py index 3d0ced12..a1a6f66a 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/erlangen_hoechstadt_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/erlangen_hoechstadt_de.py @@ -14,6 +14,14 @@ TEST_CASES = { } +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + } +} + + class Source: def __init__(self, city, street): self._city = city diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/geoport_nwm_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/geoport_nwm_de.py index 9fd04d7d..1d794951 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/geoport_nwm_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/geoport_nwm_de.py @@ -19,6 +19,13 @@ TEST_CASES = { API_URL = "https://www.geoport-nwm.de/nwm-download/Abfuhrtermine/ICS/{year}/{arg}.ics" +PARAM_TRANSLATIONS = { + "de": { + "district": "Ortsteil", + } +} + + class Source: def __init__(self, district): self._district = district diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/hausmuell_info.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/hausmuell_info.py index 8d46937a..de581e21 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/hausmuell_info.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/hausmuell_info.py @@ -191,6 +191,24 @@ def replace_special_chars_args(d: dict, replace_func=replace_special_chars) -> d return to_return +PARAM_TRANSLATIONS = { + "de": { + "subdomain": "Subdomain", + "ort": "Ort", + "ortsteil": "Ortsteil", + "strasse": "Straße", + "hausnummer": "Hausnummer", + }, + "en": { + "subdomain": "Subdomain", + "ort": "City", + "ortsteil": "District", + "strasse": "Street", + "hausnummer": "House number", + }, +} + + class Source: def __init__( self, diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/heilbronn_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/heilbronn_de.py index 0b0a5a68..989ced41 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/heilbronn_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/heilbronn_de.py @@ -49,6 +49,19 @@ ICON_MAP = { "christmastree": "mdi:pine-tree", } +PARAM_TRANSLATIONS = { + "de": { + "plz": "PLZ", + "strasse": "Straße", + "hausnr": "Hausnummer", + }, + "en": { + "plz": "Zip Code", + "strasse": "Street", + "hausnr": "House number", + }, +} + class Source: def __init__(self, plz: int, strasse: str, hausnr: str | int | None = None): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/ics.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/ics.py index 592be7fe..70f152b7 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/ics.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/ics.py @@ -105,6 +105,24 @@ HEADERS = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"} _LOGGER = logging.getLogger(__name__) +PARAM_TRANSLATIONS = { + "de": { + "url": "URL", + "file": "Datei", + "offset": "Offset", + "params": "Parameter", + "year_field": "Jahresfeld", + "method": "Methode", + "regex": "Regulärer Ausdruck", + "title_template": "Titelvorlage", + "split_at": "Trennen bei", + "version": "Version", + "verify_ssl": "SSL-Verifizierung aktivieren", + "headers": "Headers", + } +} + + class Source: def __init__( self, diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/infeo_at.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/infeo_at.py index 722997c8..68d9c4f4 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/infeo_at.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/infeo_at.py @@ -46,6 +46,17 @@ TEST_CASES = { } +PARAM_TRANSLATIONS = { + "de": { + "customer": "Kunde", + "zone": "Zone", + "city": "Ort", + "street": "Straße", + "housenumber": "Hausnummer", + } +} + + class Source: def __init__(self, customer, zone=None, city=None, street=None, housenumber=None): self._customer = customer diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/insert_it_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/insert_it_de.py index 53992afd..cce006a4 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/insert_it_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/insert_it_de.py @@ -1,12 +1,10 @@ import json -import requests - from datetime import datetime +import requests from waste_collection_schedule import Collection # type: ignore[attr-defined] -from waste_collection_schedule.service.InsertITDe import SERVICE_MAP from waste_collection_schedule.service.ICS import ICS - +from waste_collection_schedule.service.InsertITDe import SERVICE_MAP TITLE = "Insert IT Apps" DESCRIPTION = "Source for Apps by Insert IT" @@ -17,25 +15,16 @@ COUNTRY = "de" def EXTRA_INFO(): return [{"title": s["title"], "url": s["url"]} for s in SERVICE_MAP] + TEST_CASES = { "Offenbach Address": { "municipality": "Offenbach", "street": "Kaiserstraße", - "hnr": 1 + "hnr": 1, }, - "Offenbach Location ID": { - "municipality": "Offenbach", - "location_id": 7036 - }, - "Mannheim Address": { - "municipality": "Mannheim", - "street": "A 3", - "hnr": 1 - }, - "Mannheim Location ID": { - "municipality": "Mannheim", - "location_id": 430650 - } + "Offenbach Location ID": {"municipality": "Offenbach", "location_id": 7036}, + "Mannheim Address": {"municipality": "Mannheim", "street": "A 3", "hnr": 1}, + "Mannheim Location ID": {"municipality": "Mannheim", "location_id": 430650}, } @@ -62,7 +51,7 @@ ICON_MAP = { "Bio": {"icon": "mdi:leaf", "name": "Biomüll"}, "Papier": {"icon": "mdi:package-variant", "name": "Altpapier"}, "Grünschnitt": {"icon": "mdi:leaf", "name": "Grünschnitt"}, - } + }, } REGEX_MAP = { @@ -75,6 +64,15 @@ REGEX_MAP = { "Offenbach": r"Leerung:\s+(.*)\s+\(.*\)", } +PARAM_TRANSLATIONS = { + "de": { + "municipality": "Ort", + "street": "Straße", + "hnr": "Hausnummer", + "location_id": "Standort ID", + } +} + class Source: def __init__(self, municipality, street=None, hnr=None, location_id=None): @@ -87,17 +85,17 @@ class Source: municipalities = MUNICIPALITIES if municipality not in municipalities: raise Exception(f"municipality '{municipality}' not found") - + self._api_url = f"https://www.insert-it.de/{municipalities[municipality]}" self._ics = ICS(regex=REGEX_MAP.get(municipality)) - # Check if at least either location_id is set or both street and hnr are set if not ((location_id is not None) or (street is not None and hnr is not None)): - raise Exception("At least either location_id should be set or both street and hnr should be set.") - - self._uselocation = location_id is not None + raise Exception( + "At least either location_id should be set or both street and hnr should be set." + ) + self._uselocation = location_id is not None def get_street_id(self): """Return ID of matching street""" @@ -117,9 +115,8 @@ class Source: if element["Name"] == self._street: street_id = element["ID"] return street_id - + raise Exception(f"Street {self._street} not found") - def get_location_id(self, street_id): """Return ID of first matching location""" @@ -133,18 +130,20 @@ class Source: result = json.loads(r.text) if not result: - raise Exception(f"No locations found for Street ID {street_id} and House number {self._hnr}") + raise Exception( + f"No locations found for Street ID {street_id} and House number {self._hnr}" + ) for element in result: if element["StreetId"] == street_id and element["Text"] == str(self._hnr): location_id = element["ID"] return location_id - - raise Exception(f"Location for Street ID {street_id} with House number {self._hnr} not found") - + + raise Exception( + f"Location for Street ID {street_id} with House number {self._hnr} not found" + ) def fetch(self): - if not (self._uselocation): street_id = self.get_street_id() self._location = self.get_location_id(street_id) @@ -156,7 +155,6 @@ class Source: entries += self.fetch_year(now.year + 1) return entries - def fetch_year(self, year): s = requests.Session() params = {"bmsLocationId": self._location, "year": year} @@ -182,4 +180,4 @@ class Source: else: entries.append(Collection(d[0], d[1])) - return entries \ No newline at end of file + return entries diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/jumomind_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/jumomind_de.py index fac673d4..d49ca15c 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/jumomind_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/jumomind_de.py @@ -195,6 +195,17 @@ def EXTRA_INFO(): API_URL = "https://{provider}.jumomind.com/mmapp/api.php" +PARAM_TRANSLATIONS = { + "de": { + "service_id": "Service ID", + "city": "Ort", + "street": "Straße", + "city_id": "Ort ID", + "area_id": "Bereich ID", + "house_number": "Hausnummer", + } +} + LOGGER = logging.getLogger(__name__) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/karlsruhe_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/karlsruhe_de.py index 700b63eb..5080c240 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/karlsruhe_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/karlsruhe_de.py @@ -48,6 +48,20 @@ ICON_MAP = { API_URL = "https://web{i}.karlsruhe.de/service/abfall/akal/akal_{year}.php" +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + "hnr": "Hausnummer", + "ladeort": "Ladeort", + }, + "en": { + "street": "Street", + "hnr": "House number", + "ladeort": "Loading point", + }, +} + + class Source: def __init__(self, street: str, hnr: str | int, ladeort: int | None = None): self._street: str = street diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/korneuburg_stadtservice_at.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/korneuburg_stadtservice_at.py index db67794c..d1370db5 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/korneuburg_stadtservice_at.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/korneuburg_stadtservice_at.py @@ -4,7 +4,8 @@ from urllib.parse import urljoin import requests from bs4 import BeautifulSoup from waste_collection_schedule import Collection # type: ignore[attr-defined] -from waste_collection_schedule.service.ICS import ICS # type: ignore[attr-defined] +from waste_collection_schedule.service.ICS import \ + ICS # type: ignore[attr-defined] TITLE = "Stadtservice Korneuburg" DESCRIPTION = "Source for Stadtservice Korneuburg" @@ -28,6 +29,20 @@ WASTE_TYPE_URLS = { } +PARAM_TRANSLATIONS = { + "de": { + "street_name": "Straßenname", + "street_number": "Hausnummer", + "teilgebiet": "Teilgebiet", + }, + "en": { + "street_name": "Street Name", + "street_number": "Street Number", + "teilgebiet": "Subarea", + }, +} + + class Source: def __init__(self, street_name, street_number, teilgebiet=-1): self.street_name = street_name @@ -43,7 +58,6 @@ class Source: @staticmethod def extract_street_numbers(soup): - scripts = soup.findAll("script", {"type": "text/javascript"}) street_number_idx = 0 @@ -190,7 +204,6 @@ class Source: return entries def fetch(self): - ical_urls = self.get_region_links() all_entries = [] diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/ks_boerde_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/ks_boerde_de.py index 1bf58d95..0bf09775 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/ks_boerde_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/ks_boerde_de.py @@ -17,7 +17,7 @@ TEST_CASES = { "Grundschule": { "village": "Bebertal (Eiche/Hüsig)", "street": "Am Drei", - "house_number": "11", + "house_number": 11, }, "KS Börde": { "village": "Wolmirstedt", @@ -37,8 +37,17 @@ ICON_MAP = { } +PARAM_TRANSLATIONS = { + "de": { + "village": "Ort", + "street": "Straße", + "house_number": "Hausnummer", + } +} + + class Source: - def __init__(self, village: str, street: str, house_number: str): + def __init__(self, village: str, street: str, house_number: str | int): self._village = village self._street = street self._house_number = house_number @@ -69,7 +78,7 @@ class Source: # convert text into ICS object return self._ics.convert(ics) - def get_from_proxy(self, village: int = 0, street: int = 0, input: str = ""): + def get_from_proxy(self, village: int = 0, street: int = 0, input: str | int = ""): post_data = { "input": input, "ort_id": village, diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/kwb_goslar_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/kwb_goslar_de.py index 146dda39..076e3e2b 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/kwb_goslar_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/kwb_goslar_de.py @@ -20,6 +20,16 @@ ICON_MAP = { } +PARAM_TRANSLATIONS = { + "de": { + "pois": "POIS", + }, + "en": { + "pois": "POIS", + }, +} + + class Source: def __init__(self, pois): self.ics = ICS() diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/kwu_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/kwu_de.py index 45a97c28..79cc244b 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/kwu_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/kwu_de.py @@ -23,6 +23,15 @@ ICON_MAP = { } +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + "number": "Hausnummer", + } +} + + class Source: def __init__(self, city, street, number): self._city = city.strip().lower() diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/landkreis_rhoen_grabfeld.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/landkreis_rhoen_grabfeld.py index 5996d055..c9a7c71b 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/landkreis_rhoen_grabfeld.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/landkreis_rhoen_grabfeld.py @@ -11,34 +11,44 @@ TEST_CASES = { "City only": {"city": "Ostheim"}, "City + District": {"city": "Ostheim", "district": "Oberwaldbehrungen"}, "District only": {"district": "Oberwaldbehrungen"}, - "empty": {} + "empty": {}, } -API_URL = 'https://fs-api-rg.offizium.com/abfalltermine' +API_URL = "https://fs-api-rg.offizium.com/abfalltermine" -EVENT_BLACKLIST = ['Wertstoffhof Mellrichstadt', - 'Wertstoffhof Bad Königshofen', 'Wertstoffzentrum Bad Neustadt', - 'Wertstoffsammelstelle Ostheim', - 'Wertstoffsammelstelle Bischofsheim'] +EVENT_BLACKLIST = [ + "Wertstoffhof Mellrichstadt", + "Wertstoffhof Bad Königshofen", + "Wertstoffzentrum Bad Neustadt", + "Wertstoffsammelstelle Ostheim", + "Wertstoffsammelstelle Bischofsheim", +] ICON_MAP = { "Restmüll/Biotonne": "mdi:trash-can", "Gelbe Tonne": "mdi:recycle-variant", "Papiersammlung": "mdi:package-variant", - "Problemmüllsammlung": "mdi:biohazard" + "Problemmüllsammlung": "mdi:biohazard", +} + + +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "district": "Ortsteil", + } } class Source: - def __init__(self, city: str = None, district: str = None): + def __init__(self, city: str | None = None, district: str | None = None): self._city = city self._district = district def fetch(self): - r = requests.get(API_URL, params={ - "stadt": self._city, - "ortsteil": self._district - }) + r = requests.get( + API_URL, params={"stadt": self._city, "ortsteil": self._district} + ) r.raise_for_status() @@ -48,11 +58,9 @@ class Source: if event["muellart"] not in EVENT_BLACKLIST: entries.append( Collection( - date=datetime.datetime.fromisoformat( - event["termin"]).date(), + date=datetime.datetime.fromisoformat(event["termin"]).date(), t=event["muellart"], - icon=ICON_MAP.get( - event["muellart"], "mdi:trash-can") + icon=ICON_MAP.get(event["muellart"], "mdi:trash-can"), ) ) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/landkreis_wittmund_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/landkreis_wittmund_de.py index 8ad0ab90..f92a82ac 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/landkreis_wittmund_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/landkreis_wittmund_de.py @@ -1,8 +1,9 @@ -import requests import json + +import requests +from bs4 import BeautifulSoup from waste_collection_schedule import Collection # type: ignore[attr-defined] from waste_collection_schedule.service.ICS import ICS -from bs4 import BeautifulSoup TITLE = "Landkreis Wittmund" DESCRIPTION = "Source for Landkreis Wittmund waste collection." @@ -22,6 +23,14 @@ AUTOCOMPLETE_URL = "https://www.landkreis-wittmund.de/output/autocomplete.php?ou DOWNLOAD_URL = "https://www.landkreis-wittmund.de/output/options.php?ModID=48&call=ical&ArtID%5B0%5D=3105.1&ArtID%5B1%5D=1.4&ArtID%5B2%5D=1.2&ArtID%5B3%5D=1.3&ArtID%5B4%5D=1.1&pois={}&alarm=0" +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + } +} + + class Source: def __init__(self, city, street=None): self._city = city @@ -35,39 +44,31 @@ class Source: return self.fetch_ics(DOWNLOAD_URL.format(streetId)) def is_city_selection(self, tag, cityName): - return tag['value'] != "" and tag.string == self._city + return tag["value"] != "" and tag.string == self._city def fetch_city_id(self, cityName): r = requests.get(API_URL) if not r.ok: - raise Exception( - "Error: failed to fetch url: {}".format( - API_URL - ) - ) + raise Exception(f"Error: failed to fetch url: {API_URL}") - soup = BeautifulSoup(r.text, 'html.parser') - citySelection = [ a for a in soup.select('#sf_locid > option[value]') if self.is_city_selection(a, cityName) ] + soup = BeautifulSoup(r.text, "html.parser") + citySelection = [ + a + for a in soup.select("#sf_locid > option[value]") + if self.is_city_selection(a, cityName) + ] if len(citySelection) == 0: - raise Exception( - "Error: could not find id for city: '{}'".format( - cityName - ) - ) + raise Exception(f"Error: could not find id for city: '{cityName}'") if len(citySelection) > 1: - raise Exception( - "Error: non-unique match for city: '{}'".format( - cityName - ) - ) + raise Exception(f"Error: non-unique match for city: '{cityName}'") - return citySelection[0]['value'] + return citySelection[0]["value"] def fetch_street_id(self, cityId, streetName): - r = requests.get(AUTOCOMPLETE_URL.format(cityId, streetName), headers={ - "Referer": API_URL - }) + r = requests.get( + AUTOCOMPLETE_URL.format(cityId, streetName), headers={"Referer": API_URL} + ) if not r.ok: raise Exception( @@ -78,39 +79,31 @@ class Source: streets = json.loads(r.text) if streetName != None: - streetId = [ item[0] for item in streets if streetName in item[1] ] + streetId = [item[0] for item in streets if streetName in item[1]] else: - streetId = [ item[0] for item in streets ] + streetId = [item[0] for item in streets] if len(streetId) == 0: raise Exception( "Error: could not find streets for city id / street: {}, '{}'".format( - cityId, - streetName + cityId, streetName ) ) if len(streetId) > 1: raise Exception( "Error: non-unique match for city id / street: {}, '{}'".format( - cityId, - streetName + cityId, streetName ) ) return streetId[0] def fetch_ics(self, url): - r = requests.get(url, headers={ - "Referer": API_URL - }) + r = requests.get(url, headers={"Referer": API_URL}) if not r.ok: - raise Exception( - "Error: failed to fetch url: {}".format( - url - ) - ) + raise Exception(f"Error: failed to fetch url: {url}") # parse ics file r.encoding = "utf-8" diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/lindau_ch.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/lindau_ch.py index 1efb835a..4ce8b39d 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/lindau_ch.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/lindau_ch.py @@ -22,6 +22,12 @@ ICON_MAP = { "altmetalle": "mdi:nail", } +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + } +} + class Source: def __init__(self, city): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/lrasha_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/lrasha_de.py index 2a151438..435b7b0c 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/lrasha_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/lrasha_de.py @@ -2,17 +2,20 @@ import requests from waste_collection_schedule import Collection from waste_collection_schedule.service.ICS import ICS - TITLE = "Landkreis Schwäbisch Hall" DESCRIPTION = "Source for lrasha.de - Landkreis Schwäbisch Hall" URL = "https://www.lrasha.de" -TEST_CASES = { - "Ilshofen": {"location": "68345"} -} +TEST_CASES = {"Ilshofen": {"location": "68345"}} API_URL = "http://api.cross-7.de/public/calendar/396/events/ics?SecondCategoryIds=" HEADERS = {"user-agent": "Mozilla/5.0 (xxxx Windows NT 10.0; Win64; x64)"} +PARAM_TRANSLATIONS = { + "de": { + "location": "Gebiet", + } +} + class Source: def __init__(self, location): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/mags_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/mags_de.py index 3f218c44..19e080db 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/mags_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/mags_de.py @@ -1,7 +1,8 @@ +from datetime import datetime + import requests from waste_collection_schedule import Collection from waste_collection_schedule.service.ICS import ICS -from datetime import datetime TITLE = "mags Mönchengladbacher Abfall-, Grün- und Straßenbetriebe AöR" DESCRIPTION = "Source for Stadt Mönchengladbach" @@ -24,6 +25,14 @@ ICON_MAP = { "Elektrokleingeräte-Sammlung": "mdi:radio", } +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + "number": "Hausnummer", + "turnus": "Turnus", + }, +} + class Source: def __init__(self, street, number, turnus=2): @@ -35,17 +44,19 @@ class Source: def fetch(self): # fetch the ical now = datetime.now() - r = requests.get(API_URL, - params={"building_number": self._number, - "building_number_addition": "", - "street_name": self._street, - "start_month": 1, - "end_month": 12, - "start_year": now.year, - "end_year": now.year, - "turnus": self._turnus - } - ) + r = requests.get( + API_URL, + params={ + "building_number": self._number, + "building_number_addition": "", + "street_name": self._street, + "start_month": 1, + "end_month": 12, + "start_year": now.year, + "end_year": now.year, + "turnus": self._turnus, + }, + ) r.raise_for_status() # replace non-ascii character in UID, otherwise ICS converter will fail @@ -63,12 +74,6 @@ class Source: entries = [] for d in dates: - entries.append( - Collection( - date=d[0], - t=d[1], - icon=ICON_MAP.get(d[1]) - ) - ) + entries.append(Collection(date=d[0], t=d[1], icon=ICON_MAP.get(d[1]))) return entries diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/meinawb_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/meinawb_de.py index fbd5e55d..8c2a8509 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/meinawb_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/meinawb_de.py @@ -53,6 +53,15 @@ TEST_CASES = { }, } +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Strasse", + "house_number": "Hausnummer", + "address_suffix": "Hausnummerzusatz", + } +} + class Source: def __init__(self, city, street, house_number, address_suffix=""): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/monaloga_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/monaloga_de.py index 3a86f29a..3ac068c3 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/monaloga_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/monaloga_de.py @@ -39,6 +39,18 @@ GERMAN_MONTHS = { API_URL = "https://www.monaloga.de/mportal/awista-logistik/stadt-remscheid/index.php" +PARAM_TRANSLATIONS = { + "de": { + "plz": "PLZ", + "street": "Straße", + }, + "en": { + "plz": "ZIP", + "street": "Street", + }, +} + + class Source: def __init__(self, street: str, plz: str | int | None = None): self._street: str = street diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/muellabfuhr_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/muellabfuhr_de.py index c3d4021b..8f7e1707 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/muellabfuhr_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/muellabfuhr_de.py @@ -31,6 +31,15 @@ ICON_MAP = { "Biomüll": "mdi:leaf", } +PARAM_TRANSLATIONS = { + "de": { + "client": "Client", + "city": "Ort", + "district": "Ortsteil", + "street": "Straße", + } +} + class Source: def __init__(self, client, city, district=None, street=None): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/muellmax_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/muellmax_de.py index 0a734357..2919bb97 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/muellmax_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/muellmax_de.py @@ -35,6 +35,15 @@ HEADERS = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3" } +PARAM_TRANSLATIONS = { + "de": { + "service": "Service", + "mm_frm_ort_sel": "Ort", + "mm_frm_str_sel": "Straße", + "mm_frm_hnr_sel": "Hausnummer", + }, +} + # Parser for HTML checkbox class InputCheckboxParser(HTMLParser): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/muenchenstein_ch.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/muenchenstein_ch.py index a1f09b79..54e7a26e 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/muenchenstein_ch.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/muenchenstein_ch.py @@ -25,6 +25,13 @@ ICON_MAP = { } +PARAM_TRANSLATIONS = { + "de": { + "waste_district": "Abfuhrkreis", + }, +} + + class Source: def __init__(self, waste_district): self._waste_district = waste_district diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/multiple.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/multiple.py index db654329..acd717d4 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/multiple.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/multiple.py @@ -76,6 +76,13 @@ TEST_CASES = { LOGGER = logging.getLogger(__name__) +PARAM_TRANSLATIONS = { + "de": { + "source": "Quelle", + "args": "Argumente", + }, +} + def get_source(source: str, args: dict | list[dict]) -> list: if isinstance(args, list): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/offenbach_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/offenbach_de.py index 9aeec7d6..886f8752 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/offenbach_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/offenbach_de.py @@ -13,6 +13,12 @@ TEST_CASES = { "offenbach": {"f_id_location": 7036}, # KaiserStraße 1 } +PARAM_TRANSLATIONS = { + "de": { + "f_id_location": "Standort ID", + }, +} + class Source(InsertItSource): def __init__(self, f_id_location): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/potsdam_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/potsdam_de.py index 61f150e0..26f9de66 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/potsdam_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/potsdam_de.py @@ -1,9 +1,9 @@ +import json +from datetime import datetime, timedelta + import requests from waste_collection_schedule import Collection # type: ignore[attr-defined] -from datetime import datetime, timedelta -import json - TITLE = "Potsdam" DESCRIPTION = "Source for Potsdam." URL = "https://www.potsdam.de" @@ -28,7 +28,7 @@ TEST_CASES = { "rest_rhythm": 4, "papier_rhythm": 4, "bio_rhythm": 2, - } + }, } @@ -61,9 +61,36 @@ RHYTHM_MAP = { API_URL = "https://www.geben-und-nehmen-markt.de/abfallkalender/potsdam/{year}/page-data/index/page-data.json" +PARAM_TRANSLATIONS = { + "de": { + "ortsteil": "Ortsteil", + "strasse": "Straße", + "rest_rhythm": "Restabfall Rhythmus", + "papier_rhythm": "Papier Rhythmus", + "bio_rhythm": "Bio Rhythmus", + "gelb_rhythm": "Gelb Rhythmus", + }, + "en": { + "ortsteil": "District", + "strasse": "Street", + "rest_rhythm": "General waste rhythm", + "papier_rhythm": "Paper rhythm", + "bio_rhythm": "Organics rhythm", + "gelb_rhythm": "Recycling rhythm", + }, +} + class Source: - def __init__(self, ortsteil: str, strasse: str, rest_rhythm: int = 0, papier_rhythm: int = 0, bio_rhythm: int = 0, gelb_rhythm: int = 3): + def __init__( + self, + ortsteil: str, + strasse: str, + rest_rhythm: int = 0, + papier_rhythm: int = 0, + bio_rhythm: int = 0, + gelb_rhythm: int = 3, + ): self._ortsteil: str = ortsteil self._strasse: str = strasse self._rhythms = { @@ -73,7 +100,9 @@ class Source: 4: int(papier_rhythm), } - def __get_entries_for_street(self, year: int, today: datetime) -> list[dict[str, str | int]] | None: + def __get_entries_for_street( + self, year: int, today: datetime + ) -> list[dict[str, str | int]] | None: try: # get json file r = requests.get(API_URL.format(year=year)) @@ -103,28 +132,54 @@ class Source: start += timedelta(days=1) def __typematch(self, partm, partd, bin_type, turnus, schwarz, gruen, blau): - startkombi = '0401' - endekombi = '1031' + startkombi = "0401" + endekombi = "1031" - return ((bin_type == 1) and (schwarz == turnus)) or \ - ((bin_type == 2) and ((gruen == turnus) or ((gruen == 5) and (((turnus == 2) and (partm + partd >= startkombi) and (partm + partd <= endekombi)) or ((turnus == 3) and ((partm + partd < startkombi) or (partm + partd > endekombi))))))) or \ - ((bin_type == 4) and (blau == turnus)) or \ - (bin_type == 3) + return ( + ((bin_type == 1) and (schwarz == turnus)) + or ( + (bin_type == 2) + and ( + (gruen == turnus) + or ( + (gruen == 5) + and ( + ( + (turnus == 2) + and (partm + partd >= startkombi) + and (partm + partd <= endekombi) + ) + or ( + (turnus == 3) + and ( + (partm + partd < startkombi) + or (partm + partd > endekombi) + ) + ) + ) + ) + ) + ) + or ((bin_type == 4) and (blau == turnus)) + or (bin_type == 3) + ) def __date_is_collection(self, node, day: datetime, exceptions) -> bool: - return self.__date_is_collection_1_to_4(node, day, exceptions) or self.__date_is_collection5_6(node, day) + return self.__date_is_collection_1_to_4( + node, day, exceptions + ) or self.__date_is_collection5_6(node, day) def __date_is_collection5_6(self, node, day: datetime) -> bool: if not node["typ"] in (5, 6): return False - termin1 = datetime.fromisoformat( - node["termin1"].replace("Z", "+00:00")).date() - termin2 = datetime.fromisoformat( - node["termin2"].replace("Z", "+00:00")).date() + termin1 = datetime.fromisoformat(node["termin1"].replace("Z", "+00:00")).date() + termin2 = datetime.fromisoformat(node["termin2"].replace("Z", "+00:00")).date() day = day.date() return (termin1 == day) or (termin2 == day) - def __date_is_collection_1_to_4(self, node, day: datetime, exceptions, check_exception=True) -> bool: + def __date_is_collection_1_to_4( + self, node, day: datetime, exceptions, check_exception=True + ) -> bool: weekno = day.isocalendar()[1] weekeven = weekno % 2 == 0 dow = day.weekday() + 1 @@ -134,13 +189,87 @@ class Source: if day == e_from: return False if day == e_to: - return self.__date_is_collection_1_to_4(node, e_from, exceptions, check_exception=False) + return self.__date_is_collection_1_to_4( + node, e_from, exceptions, check_exception=False + ) - return (((node["rhythmus"] == 1) and self.__typematch(day.strftime("%m"), day.strftime("%d"), node["typ"], 2, self._rhythms[1], self._rhythms[2], self._rhythms[4])) and (((node["tag1"] == dow) and (node["tag2"] == 0)) or (((node["tag1"] == dow) and not weekeven) or ((node["tag2"] == dow) and weekeven)))) or \ - (((node["rhythmus"] == 2) and self.__typematch(day.strftime("%m"), day.strftime("%d"), node["typ"], 3, self._rhythms[1], self._rhythms[2], self._rhythms[4])) and (((node["woche"] == 2) and not weekeven) or ((node["woche"] == 3) and weekeven)) and (node["tag1"] == dow)) or \ - (((node["rhythmus"] == 3) and self.__typematch(day.strftime("%m"), day.strftime("%d"), node["typ"], 4, self._rhythms[1], self._rhythms[2], self._rhythms[4])) and ((weekno - node["beginn"]) % 4 == 0) and (node["tag1"] == dow)) or \ - (((node["rhythmus"] == 4) and self.__typematch(day.strftime("%m"), day.strftime("%d"), node["typ"], 1, self._rhythms[1], self._rhythms[2], self._rhythms[4])) and ((node["tag1"] == dow) or ((node["tag2"] > 0) and (node["tag2"] == dow)))) and \ - (weekno >= node["beginn"]) + return ( + ( + ( + (node["rhythmus"] == 1) + and self.__typematch( + day.strftime("%m"), + day.strftime("%d"), + node["typ"], + 2, + self._rhythms[1], + self._rhythms[2], + self._rhythms[4], + ) + ) + and ( + ((node["tag1"] == dow) and (node["tag2"] == 0)) + or ( + ((node["tag1"] == dow) and not weekeven) + or ((node["tag2"] == dow) and weekeven) + ) + ) + ) + or ( + ( + (node["rhythmus"] == 2) + and self.__typematch( + day.strftime("%m"), + day.strftime("%d"), + node["typ"], + 3, + self._rhythms[1], + self._rhythms[2], + self._rhythms[4], + ) + ) + and ( + ((node["woche"] == 2) and not weekeven) + or ((node["woche"] == 3) and weekeven) + ) + and (node["tag1"] == dow) + ) + or ( + ( + (node["rhythmus"] == 3) + and self.__typematch( + day.strftime("%m"), + day.strftime("%d"), + node["typ"], + 4, + self._rhythms[1], + self._rhythms[2], + self._rhythms[4], + ) + ) + and ((weekno - node["beginn"]) % 4 == 0) + and (node["tag1"] == dow) + ) + or ( + ( + (node["rhythmus"] == 4) + and self.__typematch( + day.strftime("%m"), + day.strftime("%d"), + node["typ"], + 1, + self._rhythms[1], + self._rhythms[2], + self._rhythms[4], + ) + ) + and ( + (node["tag1"] == dow) + or ((node["tag2"] > 0) and (node["tag2"] == dow)) + ) + ) + and (weekno >= node["beginn"]) + ) def fetch(self): today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) @@ -159,19 +288,23 @@ class Source: continue for entry in entries: - exceptions = {datetime.strptime(d_from, "%d.%m.%Y"): datetime.strptime(d_to, "%d.%m.%Y") for d_from, d_to in json.loads(entry["ausnahmen"]).items()} + exceptions = { + datetime.strptime(d_from, "%d.%m.%Y"): datetime.strptime( + d_to, "%d.%m.%Y" + ) + for d_from, d_to in json.loads(entry["ausnahmen"]).items() + } icon = ICON_MAP.get(entry["typ"]) type = TYPE_MAP.get(entry["typ"]) rhythm_type = self._rhythms.get(entry["typ"]) - if (rhythm_type in RHYTHM_MAP): + if rhythm_type in RHYTHM_MAP: type += " (" + RHYTHM_MAP.get(rhythm_type) + ")" - for day in self.__generate_dates(today, datetime(year+1, 1, 1)): + for day in self.__generate_dates(today, datetime(year + 1, 1, 1)): if not self.__date_is_collection(entry, day, exceptions): continue - collections.append(Collection( - date=day.date(), t=type, icon=icon)) + collections.append(Collection(date=day.date(), t=type, icon=icon)) collections.sort(key=lambda x: x.date) return collections diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/real_luzern_ch.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/real_luzern_ch.py index 1d7149b2..f3a73f80 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/real_luzern_ch.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/real_luzern_ch.py @@ -35,6 +35,14 @@ OLD_WASTE_NAME = ( API_URL = "https://www.real-luzern.ch/abfall/sammeldienst/abfallkalender/" +PARAM_TRANSLATIONS = { + "de": { + "municipality_id": "Orts ID", + "street_id": "Strassen ID", + }, +} + + class Source: def __init__(self, municipality_id: str | int, street_id: str | int | None = None): self._municipality_id = municipality_id diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/regioentsorgung_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/regioentsorgung_de.py index 4ea48006..99bfce39 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/regioentsorgung_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/regioentsorgung_de.py @@ -18,6 +18,15 @@ HEADERS = { } +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + "house_number": "Hausnummer", + }, +} + + class Source: def __init__(self, city, street, house_number): self.city = city diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/rh_entsorgung_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/rh_entsorgung_de.py index d0b41cdd..028f5c46 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/rh_entsorgung_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/rh_entsorgung_de.py @@ -1,4 +1,5 @@ -from waste_collection_schedule.source.jumomind_de import Source as JumomindSource +from waste_collection_schedule.source.jumomind_de import \ + Source as JumomindSource TITLE = "Rhein-Hunsrück Entsorgung (RHE)" DESCRIPTION = "Source for RHE (Rhein Hunsrück Entsorgung)." @@ -18,6 +19,16 @@ TEST_CASES = { } +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + "house_number": "Hausnummer", + "address_suffix": "Hausnummerzusatz", + }, +} + + class Source(JumomindSource): def __init__( self, city: str, street: str, house_number: int, address_suffix: str = "" diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/sbazv_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/sbazv_de.py index a7d1b2db..6ab59685 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/sbazv_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/sbazv_de.py @@ -24,6 +24,14 @@ ICON_MAP = { # _LOGGER = logging.getLogger(__name__) +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "district": "Ortsteil", + "street": "Straße", + }, +} + class Source: def __init__(self, city, district, street=None): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/sector27_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/sector27_de.py index d3cccb6c..81bb801f 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/sector27_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/sector27_de.py @@ -25,6 +25,13 @@ CITIES = { HEADERS = {"user-agent": "Mozilla/5.0"} +PARAM_TRANSLATIONS = { + "de": { + "city": "Ort", + "street": "Straße", + }, +} + class Source: def __init__(self, city, street): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/stuttgart_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/stuttgart_de.py index 4d6926ce..181a5f1e 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/stuttgart_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/stuttgart_de.py @@ -10,6 +10,14 @@ URL = "https://service.stuttgart.de" TEST_CASES = {"Im Steinengarten 7": {"street": "Im Steinengarten", "streetnr": 7}} +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + "streetnr": "Hausnummer", + } +} + + # Parser for HTML checkbox class InputCheckboxParser(HTMLParser): def __init__(self, name): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/tbv_velbert_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/tbv_velbert_de.py index 1b0ad7d0..f53bc9a0 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/tbv_velbert_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/tbv_velbert_de.py @@ -24,6 +24,12 @@ ICON_MAP = { _LOGGER = logging.getLogger(__name__) +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + } +} + class Source: def __init__(self, street): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/tonnenleerung_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/tonnenleerung_de.py index 6f2ec0e3..4b617e18 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/tonnenleerung_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/tonnenleerung_de.py @@ -46,6 +46,12 @@ NAME_2_TYPE = { "grau4Array": "grau4", } +PARAM_TRANSLATIONS = { + "de": { + "url": "URL", + } +} + class Source: def __init__(self, url: str): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/umweltverbaende_at.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/umweltverbaende_at.py index 5f3e30c6..ea4381c1 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/umweltverbaende_at.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/umweltverbaende_at.py @@ -197,6 +197,16 @@ ICON_MAP = { "Windeltonne": "mdi:baby", } +PARAM_TRANSLATIONS = { + "de": { + "district": "Gebiet", + "municipal": "Gemeinde", + "calendar": "Kalender", + "calendar_title_separator": "Kalendertitel Seperator", + "calendar_splitter": "Kalendereintrag-Trenner", + } +} + class Source: def __init__( diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/was_wolfsburg_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/was_wolfsburg_de.py index a01e9db8..1ea13628 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/was_wolfsburg_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/was_wolfsburg_de.py @@ -19,6 +19,13 @@ ICON_MAP = { "Altpapier": "mdi:file-document-outline", } +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + "city": "Ort", + } +} + class Source: def __init__(self, street: str | None, city: str | None): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/wermelskirchen_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/wermelskirchen_de.py index 62bb25ad..d2c80f8d 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/wermelskirchen_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/wermelskirchen_de.py @@ -46,6 +46,14 @@ ICON_MAP = { } +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + "house_number": "Hausnummer", + } +} + + class Source: def __init__(self, street, house_number): self._street = street diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/wsz_moosburg_at.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/wsz_moosburg_at.py index c65b5703..5a0d8237 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/wsz_moosburg_at.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/wsz_moosburg_at.py @@ -44,9 +44,24 @@ MUNICIPAL_CHOICES = { "Techelsberg": "20435", } +PARAM_TRANSLATIONS = { + "de": { + "address_id": "Adressen ID", + "municipal": "Gemeinde", + "address": "Adresse", + "street": "Straße", + } +} + class Source: - def __init__(self, address_id=None, municipal=None, address=None, street=None): + def __init__( + self, + address_id: int | None = None, + municipal: str | None = None, + address: str | None = None, + street: str | None = None, + ): if address_id is not None: self._address_id = address_id elif municipal is not None and address is not None and street is not None: @@ -55,7 +70,7 @@ class Source: ) else: raise Exception( - "Invalid argument count, provide either address_id or all 3 address parts (municipal, address, street)" + "You must provide either an (address_id) or (municipal, address, street)" ) def fetch(self): diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/wuerzburg_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/wuerzburg_de.py index e06f31bc..61860615 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/wuerzburg_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/wuerzburg_de.py @@ -18,14 +18,22 @@ API_URL = "https://www.wuerzburg.de/themen/umwelt-klima/vorsorge-entsorgung/abfa HEADERS = {"user-agent": "Mozilla/5.0 (xxxx Windows NT 10.0; Win64; x64)"} +PARAM_TRANSLATIONS = { + "de": { + "district": "Stadtteil", + "street": "Straße", + } +} + + class Source: - def __init__(self, district: str = None, street: str = None): + def __init__(self, district: str | None = None, street: str | None = None): self._district = district self._street = street self._district_id = None @staticmethod - def map_district_id(district: str = None, street: str = None): + def map_district_id(district: str | None = None, street: str | None = None): """Map `street` or `district` to `district_id`, giving priority to `street`. Parameters must exactly be the same as visible in dropdowns on `URL`. diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/zakb_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/zakb_de.py index 6624080e..7c69bf71 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/zakb_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/zakb_de.py @@ -10,7 +10,7 @@ TEST_CASES = { "ort": "Abtsteinach", "strasse": "Am Hofböhl", "hnr": "1", - "hnr_zusatz": "" + "hnr_zusatz": "", }, "Gorxheimertal, Am Herrschaftswald 10": { "ort": "Gorxheimertal", @@ -21,13 +21,13 @@ TEST_CASES = { "ort": "Rimbach", "strasse": "Ahornweg", "hnr": "1", - "hnr_zusatz": "B" + "hnr_zusatz": "B", }, "Zwingenberg, Diefenbachstraße 57": { "ort": "Zwingenberg", "strasse": "Diefenbachstraße", "hnr": 57, - "hnr_zusatz": "" + "hnr_zusatz": "", }, } @@ -46,6 +46,22 @@ ICON_MAP = { API_URL = "https://www.zakb.de/online-service/abfallkalender/" +PARAM_TRANSLATIONS = { + "de": { + "ort": "Ort", + "strasse": "Straße", + "hnr": "Hausnummer", + "hnr_zusatz": "Hausnummerzusatz", + }, + "en": { + "ort": "City", + "strasse": "Street", + "hnr": "House number", + "hnr_zusatz": "House number addition", + }, +} + + class Source: def __init__(self, ort: str, strasse: str, hnr: str | int, hnr_zusatz: str = ""): self._ort: str = ort.replace(" ", "+") @@ -55,7 +71,6 @@ class Source: self._ics = ICS() def fetch(self): - # inizilize session session = requests.Session() @@ -91,7 +106,9 @@ class Source: # make request to get ical file r = session.post( - API_URL, data={"submitAction": "filedownload_ICAL", "pageName": "Terminliste"}) + API_URL, + data={"submitAction": "filedownload_ICAL", "pageName": "Terminliste"}, + ) r.raise_for_status() dates = self._ics.convert(r.text) diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/zva_sek_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/zva_sek_de.py index 491c6a22..cd3e41b5 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/zva_sek_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/zva_sek_de.py @@ -1,9 +1,8 @@ import re -import requests from datetime import datetime +import requests from bs4 import BeautifulSoup - from waste_collection_schedule import Collection # type: ignore[attr-defined] from waste_collection_schedule.service.ICS import ICS @@ -34,17 +33,27 @@ TEST_CASES = { "ortsteil": "Guxhagen", }, } -SERVLET = ( - "https://www.zva-sek.de/module/abfallkalender/generate_ical.php" -) +SERVLET = "https://www.zva-sek.de/module/abfallkalender/generate_ical.php" MAIN_URL = "https://www.zva-sek.de/online-dienste/abfallkalender-{year}/{file}" API_URL = "https://www.zva-sek.de/module/abfallkalender/{file}" +PARAM_TRANSLATIONS = { + "de": { + "bezirk": "Abfuhrbezirk", + "strasse": "Straße", + "ortsteil": "Ortsteil", + }, + "en": { + "bezirk": "City district", + "strasse": "Street", + "ortsteil": "District", + }, +} + + class Source: - def __init__( - self, bezirk: str, ortsteil: str, strasse: str = None - ): + def __init__(self, bezirk: str, ortsteil: str, strasse: str | None = None): self._bezirk = bezirk self._ortsteil = ortsteil self._street = strasse if strasse != "" else None @@ -58,13 +67,13 @@ class Source: ortsteil_id = None # get bezirke id - r = session.get(MAIN_URL.format( - year=year, file=f"abfallkalender-{year}.html")) - if (r.status_code == 404): # try last year URL if this year is not available - r = session.get(MAIN_URL.format( - year=year, file=f"abfallkalender-{year-1}.html")) + r = session.get(MAIN_URL.format(year=year, file=f"abfallkalender-{year}.html")) + if r.status_code == 404: # try last year URL if this year is not available + r = session.get( + MAIN_URL.format(year=year, file=f"abfallkalender-{year-1}.html") + ) r.raise_for_status() - + soup = BeautifulSoup(r.text, features="html.parser") for option in soup.find("select", {"name": "ak_bezirk"}).find_all("option"): if option.text.lower() == self._bezirk.lower(): @@ -77,13 +86,14 @@ class Source: raise Exception("bezirk not found") # get ortsteil id - r = session.get(API_URL.format( - file="get_ortsteile.php"), params={"bez_id": bezirk_id}) + r = session.get( + API_URL.format(file="get_ortsteile.php"), params={"bez_id": bezirk_id} + ) r.raise_for_status() last_orts_id = None for part in r.text.split(";")[2:-1]: # part is "f.ak_ortsteil.options[5].text = 'Alte Kasseler Straße'" or "ak_ortsteil.options[6].value = '2'" - if ("length" in part): + if "length" in part: continue if part.split(" = ")[1][1:-1].lower() == self._ortsteil.lower(): ortsteil_id = last_orts_id @@ -97,13 +107,15 @@ class Source: # get street id if steet given if self._street is not None: - r = session.get(API_URL.format( - file="get_strassen.php"), params={"ot_id": ortsteil_id.split("-")[0]}) + r = session.get( + API_URL.format(file="get_strassen.php"), + params={"ot_id": ortsteil_id.split("-")[0]}, + ) r.raise_for_status() last_street_id = None - for part in r.text.split(";")[2:-1]: + for part in r.text.split(";")[2:-1]: # part is "f.ak_strasse.options[5].text = 'Alte Kasseler Straße'" or "ak_strasse.options[6].value = '2'" - if ("length" in part): + if "length" in part: continue if part.split(" = ")[1][1:-1].lower() == self._street.lower(): street_id = last_street_id @@ -113,15 +125,19 @@ class Source: if not street_id: raise Exception("street not found") - entries = self.get_calendar_data(year, bezirk_id, ortsteil_id, street_id, session) + entries = self.get_calendar_data( + year, bezirk_id, ortsteil_id, street_id, session + ) if datetime.now().month >= 11: try: - entries += self.get_calendar_data(year+1, bezirk_id, ortsteil_id, street_id, session) + entries += self.get_calendar_data( + year + 1, bezirk_id, ortsteil_id, street_id, session + ) except Exception: pass return entries - - def get_calendar_data(self, year, bezirk_id, ortsteil_id,street_id, session): + + def get_calendar_data(self, year, bezirk_id, ortsteil_id, street_id, session): args = { "year": str(year), "ak_bezirk": bezirk_id, @@ -143,6 +159,7 @@ class Source: entries = [] for d in dates: - entries.append(Collection(d[0], re.sub( - "[ ]*am [0-9]+.[0-9]+.[0-9]+[ ]*", "", d[1]))) + entries.append( + Collection(d[0], re.sub("[ ]*am [0-9]+.[0-9]+.[0-9]+[ ]*", "", d[1])) + ) return entries diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/zva_wmk_de.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/zva_wmk_de.py index c0ee4a82..2ada807e 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/zva_wmk_de.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/zva_wmk_de.py @@ -13,6 +13,13 @@ TEST_CASES = { "Vockerode": {"city": "Meißner - Vockerode", "street": "Feuerwehr"}, } +PARAM_TRANSLATIONS = { + "de": { + "street": "Straße", + "city": "Ort", + } +} + class Source: def __init__(self, city, street): diff --git a/update_docu_links.py b/update_docu_links.py index d027bd63..94d476b6 100755 --- a/update_docu_links.py +++ b/update_docu_links.py @@ -123,6 +123,7 @@ def split_camel_and_snake_case(s): s = re.sub("([a-z0-9])([A-Z])", r"\1 \2", s) # Split CamelCase return s.replace("_", " ").split() # Split snake_case + def update_edpevent_se(modules: dict[str, ModuleType]): module = modules.get("edpevent_se") if not module: @@ -136,6 +137,7 @@ def update_edpevent_se(modules: dict[str, ModuleType]): _patch_file("doc/source/edpevent_se.md", "service", str) + def main() -> None: sources: list[SourceInfo] = [] @@ -241,7 +243,7 @@ def browse_sources() -> list[SourceInfo]: update_app_abfallplus_de(modules) update_abfallnavi_de(modules) update_edpevent_se(modules) - + return sources @@ -401,11 +403,20 @@ def update_json( ) params.update(e.params) - for key, value in e.custom_param_translation.items(): - if key in param_translations: - param_translations[key].update(value) + for lang, translations in e.custom_param_translation.items(): + if lang in param_translations: + for key, value in translations.items(): + if ( + key in param_translations[lang] + and value != param_translations[lang][key] + ): + print( + f'Conflicting translations for language {lang} "{key}" => "{value}" ({e.module}) AND "{param_translations[lang][key]}"' + ) + + param_translations[lang].update(translations) else: - param_translations[key] = value.copy() + param_translations[lang] = translations.copy() # output["Generic"] = [{"title": "ICS", "module": "ics", "default_params": {}}, {"title": "Static", "module": "static", "default_params": {}}]