allow to use other fields than summary in ical source for event title (#663)

* allow to use other fields than summary in ical source for event title

* add jinja2 to requirements.txt
This commit is contained in:
Sebastian Plattner
2023-10-24 14:26:38 +02:00
committed by GitHub
parent f22509c7f3
commit 9be0bc9b28
5 changed files with 122 additions and 16 deletions

View File

@@ -3,6 +3,7 @@ import logging
import re
from typing import Any, List, Optional, Tuple
import jinja2
from icalevents import icalevents
_LOGGER = logging.getLogger(__name__)
@@ -14,6 +15,7 @@ class ICS:
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 @@ class ICS:
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 @@ class ICS:
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

View File

@@ -4,18 +4,28 @@ import re
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 @@ class ICS_v1:
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

View File

@@ -115,6 +115,7 @@ class Source:
year_field=None,
method="GET",
regex=None,
title_template="{{date.summary}}",
split_at=None,
version=2,
verify_ssl=True,
@@ -125,9 +126,19 @@ class Source:
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

View File

@@ -121,6 +121,7 @@ waste_collection_schedule:
version: 2
verify_ssl: VERIFY_SSL
headers: HEADERS
title_template: "{{date.summary}}"
```
### Configuration Variables
@@ -222,6 +223,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
***
@@ -295,3 +301,72 @@ waste_collection_schedule:
```
Removes the needless prefix "Abfuhr: " from the waste collection type.
***
### FES Frankfurt
```yaml
waste_collection_schedule:
sources:
- name: ics
args:
url: https://www.fes-frankfurt.de/abfallkalender/<your-id>.ics
split_at: " \/ "
regex: "(.*)\\s+\\|"
```
***
### Abfallwirtschaftsbetrieb Ilm-Kreis
Go to the [service provider website](https://aik.ilm-kreis.de/Abfuhrtermine/) and select location and street. Selection of desired waste types is optional. Afterwards an iCal calendar export is provided. Download it and find the download URL. Some parameters of the URL can be omitted. (e.g. `kat`, `ArtID`, `alarm`)
Important: The base url of the provider's website `https://aik.ilm-kreis.de` needs to be set as a [custom header](#custom-headers) `referer`. Otherwise you'll get an HTTP 403 error.
```yaml
waste_collection_schedule:
sources:
- name: ics
args:
url: "https://aik.ilm-kreis.de/output/options.php?ModID=48&call=ical&=&ArtID[0]=1.1&ArtID[1]=1.4&ArtID[2]=1.2&pois=3053.562&kat=1,&alarm=0"
headers:
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
```

View File

@@ -17,3 +17,4 @@ soupsieve==2.4.1
urllib3==2.0.4
x-wr-timezone==0.0.5
zope.interface==6.0
jinja2=3.1.2