Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 4 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import re
from typing import Any, List, Optional, Tuple

import jinja2
from icalevents import icalevents

_LOGGER = logging.getLogger(__name__)
Expand All @@ -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
Expand All @@ -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(
Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ def __init__(
year_field=None,
method="GET",
regex=None,
title_template="{{date.summary}}",
split_at=None,
version=2,
verify_ssl=True,
Expand All @@ -125,9 +126,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
Expand Down
75 changes: 75 additions & 0 deletions doc/source/ics.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ waste_collection_schedule:
version: 2
verify_ssl: VERIFY_SSL
headers: HEADERS
title_template: "{{date.summary}}"
```

### Configuration Variables
Expand Down Expand Up @@ -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

***
Expand Down Expand Up @@ -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
```
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading