Compare commits

..

4 commits

5 changed files with 121 additions and 33 deletions

View file

@ -5,7 +5,7 @@ title: Willkommen beim PC Stammertal
html: html:
<h3>Unser nächster Anlass: </h3><br/> <h3>Unser nächster Anlass: </h3><br/>
<div class="nextevent">Leider unbekannt, aber <strong>frag mal den Vorstand</strong> der müsste es wissen</div> <div class="nextevent">Sonntag <strong>15. Dezember, Pistolen Gangfisch Schiessen</strong>, Ermatingen</div>
<div class="threecolumn"> <div class="threecolumn">
<div> <div>
<a href="termine/"><img src=" /images/termine_square.jpg" alt="Terminkalender"> All unsere Termine</a> <a href="termine/"><img src=" /images/termine_square.jpg" alt="Terminkalender"> All unsere Termine</a>
@ -22,8 +22,3 @@ _template:
page.html page.html

View file

@ -4,14 +4,6 @@ title: Termine
--- ---
body: body:
* <div>Pistolen Gangfisch Schiessen</div>&nbsp;
* <div>So. 8. Dezember 2024</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Ermatingen</div>&nbsp;
* <div>Pistolen Gangfisch Schiessen</div>&nbsp;
* <div>Sa. 14. Dezember 2024</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Ermatingen</div>&nbsp;
* <div>Pistolen Gangfisch Schiessen</div>&nbsp; * <div>Pistolen Gangfisch Schiessen</div>&nbsp;
* <div>So. 15. Dezember 2024</div>&nbsp; * <div>So. 15. Dezember 2024</div>&nbsp;
* <div>&nbsp;</div>&nbsp; * <div>&nbsp;</div>&nbsp;
@ -36,7 +28,7 @@ body:
* <div>Sa. 20. September 2025</div>&nbsp; * <div>Sa. 20. September 2025</div>&nbsp;
* <div>13:00</div>&nbsp; * <div>13:00</div>&nbsp;
* <div>&nbsp;</div>&nbsp; * <div>&nbsp;</div>&nbsp;
* <div>Schwaderlohschiessen</div>&nbsp; * <div>Schwaderlohschiessen (unser Schiesstag)</div>&nbsp;
* <div>Di. 23. September 2025</div>&nbsp; * <div>Di. 23. September 2025</div>&nbsp;
* <div>17:00</div>&nbsp; * <div>17:00</div>&nbsp;
* <div>&nbsp;</div>&nbsp; * <div>&nbsp;</div>&nbsp;

View file

@ -6,21 +6,21 @@ body:
* <div>Ulrich Roland</div>&nbsp; * <div>Ulrich Roland</div>&nbsp;
* <div>Präsident</div>&nbsp; * <div>Präsident</div>&nbsp;
* <div>praesidium@pc-stammertal.ch</div>&nbsp; * <div><a href="mailto:praesidium@pc-stammertal.ch">praesidium@pc-stammertal.ch</a></div>&nbsp;
* <div>Ita Regula</div>&nbsp; * <div>Ita Regula</div>&nbsp;
* <div>Kassierin</div>&nbsp; * <div>Kassierin</div>&nbsp;
* <div>kasse@pc-stammertal.ch</div>&nbsp; * <div><a href="mailto:kasse@pc-stammertal.ch">kasse@pc-stammertal.ch</a></div>&nbsp;
* <div>Arnold Sonja</div>&nbsp; * <div>Arnold Sonja</div>&nbsp;
* <div>Aktuarin</div>&nbsp; * <div>Aktuarin</div>&nbsp;
* <div>aktuariat@pc-stammertal.ch</div>&nbsp; * <div><a href="mailto:aktuariat@pc-stammertal.ch">aktuariat@pc-stammertal.ch</a></div>&nbsp;
* <div>Müller Konrad</div>&nbsp; * <div>Müller Konrad</div>&nbsp;
* <div>1. Schützenmeister</div>&nbsp; * <div>1. Schützenmeister</div>&nbsp;
* <div>schiesswesen@pc-stammertal.ch</div>&nbsp; * <div><a href="mailto:schiesswesen@pc-stammertal.ch">schiesswesen@pc-stammertal.ch</a></div>&nbsp;
* <div>Bollinger Reto</div>&nbsp; * <div>Bollinger Reto</div>&nbsp;
* <div>Schützenmeister, Beisitz</div>&nbsp; * <div>Schützenmeister, Beisitz</div>&nbsp;
* <div>beisitz@pc-stammertal.ch</div>&nbsp; * <div><a href="mailto:beisitz@pc-stammertal.ch">beisitz@pc-stammertal.ch</a></div>&nbsp;
* <div>Horvath Richard</div>&nbsp; * <div>Horvath Richard</div>&nbsp;
* <div>Schützenmeister, Fähnrich, Standwart</div>&nbsp; * <div>Schützenmeister, Fähnrich, Standwart</div>&nbsp;
* <div>infrastruktur@pc-stammertal.ch</div>&nbsp; * <div><a href="mailto:infrastruktur@pc-stammertal.ch">infrastruktur@pc-stammertal.ch</a></div>&nbsp;
--- ---
_template: page.html _template: page.html

View file

@ -2,16 +2,67 @@
import sys import sys
from pathlib import Path from pathlib import Path
from datetime import datetime, date from datetime import datetime, date, timedelta
from typing import Optional, NamedTuple from typing import Optional, NamedTuple
from dataclasses import dataclass from dataclasses import dataclass
from copy import deepcopy
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from icalendar import Calendar from icalendar import Calendar, Event
import recurring_ical_events import recurring_ical_events
import locale import locale
#This is duplicated code from calendar-fetcher.py
def split_multiday_events(events):
"""
Split multi-day events into separate daily events.
Args:
events: Iterator of iCal events
Returns:
List of events where multi-day events are split into daily events
"""
split_events = []
for event in events:
# Get start and end dates
start = event.get('dtstart').dt
end = event.get('dtend').dt if event.get('dtend') else start
# Convert datetime to date if needed
if isinstance(start, datetime):
start = start.date()
if isinstance(end, datetime):
end = end.date()
# If it's a single day event or not a date/datetime, add as is
if not isinstance(start, date) or not isinstance(end, date) or start == end:
split_events.append(event)
continue
# For multi-day events, create separate events for each day
current_date = start
while current_date < end:
# Create a copy of the original event
daily_event = Event()
for key in event:
daily_event[key] = deepcopy(event[key])
# Update the date for this instance
daily_event['dtstart'].dt = current_date
if 'dtend' in daily_event:
daily_event['dtend'].dt = current_date + timedelta(days=1)
split_events.append(daily_event)
current_date += timedelta(days=1)
return split_events
@dataclass @dataclass
class EventDetails: class EventDetails:
weekday: str weekday: str
@ -48,7 +99,7 @@ html:
{self.fallback_html} {self.fallback_html}
<div class="threecolumn"> <div class="threecolumn">
<div> <div>
<a href="termine/"><img src=" /images/termine_square.jpg" alt="Terminkalender"> All unsere Termine</a><!-- Fallback> <a href="termine/"><img src=" /images/termine_square.jpg" alt="Terminkalender"> All unsere Termine</a>
</div> </div>
<div> <div>
<a href="about/"><img src="/images/about_square.jpg" alt="Buch"> Alle Infos über uns</a> <a href="about/"><img src="/images/about_square.jpg" alt="Buch"> Alle Infos über uns</a>
@ -83,8 +134,8 @@ page.html
def get_next_event(self, calendar: Calendar) -> Optional[EventDetails]: def get_next_event(self, calendar: Calendar) -> Optional[EventDetails]:
try: try:
events = recurring_ical_events.of(calendar).after(datetime.now()) events = split_multiday_events(recurring_ical_events.of(calendar).after(datetime.now()))
event = next(events) event = events[0]
start = event.get('dtstart').dt start = event.get('dtstart').dt
return EventDetails( return EventDetails(

View file

@ -1,20 +1,70 @@
from datetime import datetime, date from datetime import datetime, date, timedelta
import recurring_ical_events import recurring_ical_events
import requests import requests
from icalendar import Calendar from copy import deepcopy
from icalendar import Calendar, Event
import locale import locale
import sys import sys
#This is duplicated code from calendar-fetcher-main.py
def split_multiday_events(events):
"""
Split multi-day events into separate daily events.
Args:
events: Iterator of iCal events
Returns:
List of events where multi-day events are split into daily events
"""
split_events = []
for event in events:
# Get start and end dates
start = event.get('dtstart').dt
end = event.get('dtend').dt if event.get('dtend') else start
# Convert datetime to date if needed
if isinstance(start, datetime):
start = start.date()
if isinstance(end, datetime):
end = end.date()
# If it's a single day event or not a date/datetime, add as is
if not isinstance(start, date) or not isinstance(end, date) or start == end:
split_events.append(event)
continue
# For multi-day events, create separate events for each day
current_date = start
while current_date < end:
# Create a copy of the original event
daily_event = Event()
for key in event:
daily_event[key] = deepcopy(event[key])
# Update the date for this instance
daily_event['dtstart'].dt = current_date
if 'dtend' in daily_event:
daily_event['dtend'].dt = current_date + timedelta(days=1)
split_events.append(daily_event)
current_date += timedelta(days=1)
return split_events
def fetch_upcoming_events(ics_url): def fetch_upcoming_events(ics_url):
# Set German locale # Set German locale
locale.setlocale(locale.LC_TIME, 'de_DE.UTF-8') locale.setlocale(locale.LC_TIME, 'de_DE.UTF-8')
response = requests.get(ics_url) response = requests.get(ics_url)
calendar = Calendar.from_ical(response.content) calendar = Calendar.from_ical(response.content)
# Get recurring and non-recurring events events = split_multiday_events(recurring_ical_events.of(calendar).after(datetime.now()))
events = recurring_ical_events.of(calendar).after(datetime.now())
for event in events: for event in events:
start = event.get('dtstart').dt start = event.get('dtstart').dt
out_summary = event.get('summary') out_summary = event.get('summary')