diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS.py b/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS.py index 6b73387a3..b81a6390e 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS.py @@ -2,6 +2,7 @@ import logging import re from typing import Any, List, Optional, Tuple +import jinja2 from icalevents import icalevents @@ -14,6 +15,7 @@ def __init__( offset: Optional[int] = None, regex: Optional[str] = None, split_at: Optional[str] = None, + title_template: Optional[str] = "{{date.summary}}", ): self._offset = offset self._regex = None @@ -25,6 +27,8 @@ def __init__( if split_at is not None: self._split_at = re.compile(split_at) + self._title_template = title_template + def convert(self, ics_data: str) -> List[Tuple[datetime.date, str]]: # calculate start- and end-date for recurring events start_date = datetime.datetime.now().replace( @@ -55,17 +59,19 @@ def convert(self, ics_data: str) -> List[Tuple[datetime.date, str]]: if self._offset is not None: dtstart += datetime.timedelta(days=self._offset) - # calculate waste type - summary = str(e.summary) + environment = jinja2.Environment() + title_template = environment.from_string(self._title_template) + entry_title = title_template.render(date=e) if self._regex is not None: - if match := self._regex.match(summary): - summary = match.group(1) + match = self._regex.match(entry_title) + if match: + entry_title = match.group(1) if self._split_at is not None: - summary = re.split(self._split_at, summary) - entries.extend((dtstart, t.strip().title()) for t in summary) + entry_title = re.split(self._split_at, entry_title) + entries.extend((dtstart, t.strip().title()) for t in entry_title) else: - entries.append((dtstart, summary)) + entries.append((dtstart, entry_title)) return entries diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS_v1.py b/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS_v1.py index 765b6c7ba..999005e9f 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS_v1.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/service/ICS_v1.py @@ -4,18 +4,28 @@ import icalendar import recurring_ical_events +import jinja2 + _LOGGER = logging.getLogger(__name__) class ICS_v1: - def __init__(self, offset=None, regex=None, split_at=None): + def __init__( + self, + offset=None, + regex=None, + split_at=None, + title_template="{{date.summary}}", + ): self._offset = offset self._regex = None if regex is not None: self._regex = re.compile(regex) self._split_at = split_at + self._title_template = title_template + def convert(self, ics_data): # parse ics file calendar = icalendar.Calendar.from_ical(ics_data) @@ -43,17 +53,20 @@ def convert(self, ics_data): dtstart += datetime.timedelta(days=self._offset) # calculate waste type - summary = str(e.get("summary")) + environment = jinja2.Environment() + title_template = environment.from_string(self._title_template) + entry_title = title_template.render(date=e) + if self._regex is not None: - match = self._regex.match(summary) + match = self._regex.match(entry_title) if match: - summary = match.group(1) + entry_title = match.group(1) if self._split_at is not None: - summary = re.split(self._split_at, summary) - for t in summary: + entry_title = re.split(self._split_at, entry_title) + for t in entry_title: entries.append((dtstart, t.strip().title())) else: - entries.append((dtstart, summary)) + entries.append((dtstart, entry_title)) return entries 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 8a5b36a4a..3d2664144 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 @@ -135,6 +135,7 @@ def __init__( year_field=None, method="GET", regex=None, + title_template="{{date.summary}}", split_at=None, version=2, verify_ssl=True, @@ -145,9 +146,19 @@ def __init__( if bool(self._url is not None) == bool(self._file is not None): raise RuntimeError("Specify either url or file") if version == 1: - self._ics = ICS_v1(offset=offset, split_at=split_at, regex=regex) + self._ics = ICS_v1( + offset=offset, + split_at=split_at, + regex=regex, + title_template=title_template, + ) else: - self._ics = ICS(offset=offset, split_at=split_at, regex=regex) + self._ics = ICS( + offset=offset, + split_at=split_at, + regex=regex, + title_template=title_template, + ) self._params = params self._year_field = year_field # replace this field in params with current year self._method = method # The method to send the params diff --git a/doc/source/ics.md b/doc/source/ics.md index 1c604f704..b00ebe2ea 100644 --- a/doc/source/ics.md +++ b/doc/source/ics.md @@ -97,6 +97,7 @@ waste_collection_schedule: version: 2 verify_ssl: VERIFY_SSL headers: HEADERS + title_template: "{{date.summary}}" ``` ### Configuration Variables @@ -198,6 +199,11 @@ Add custom headers to HTTP request, e.g. `referer`. By default, the `user-agent` See also [example](#custom-headers) below. +**title_template** +*(str) (optional, default: `{{date.summary}}`)* + +template for the event title. `date` is the event object depending on the selected ICS file parser version. + ## Examples and Notes *** @@ -855,3 +861,39 @@ waste_collection_schedule: referer: "https://aik.ilm-kreis.de" calendar_title: Abfuhrtermine Witzleben ``` + + +### Münsingen, Canton of Bern, Switzerland + +Go to [Abfallkalender](https://www.muensingen.ch/de/verwaltung/dienstleistungen/detail/detail.php?i=90) to get the url of the ICal file. + +```yaml +waste_collection_schedule: + sources: + - name: ics + args: + url: "https://www.muensingen.ch/de/verwaltung/dokumente/dokumente/Papier-und-Kartonabfuhr-{%Y}.ics" + version: 1 + title_template: "{{date.summary}} {{date.location}}" + calendar_title: "Papier-und-Kartonabfuhr" + customize: + - type: Papier und Karton Gebiet Ost + alias: Gebiet Ost + show: false + icon: mdi:recycle + - type: Papier und Karton Gebiet West + alias: Gebiet West + icon: mdi:recycle + - type: Papier und Karton Gebiet Ost und West + alias: Gebiet Ost und West + icon: mdi:recycle + - name: ics + args: + url: "https://www.muensingen.ch/de/verwaltung/dokumente/dokumente/Gartenabfaelle-{%Y}.ics" + version: 1 + calendar_title: "Gartenabfaelle" + customize: + - type: "Grüngut" + alias: "Grüngut" + icon: mdi:leaf-circle +```