Updating homepage (ZHKSF is over now) and fixed updating of +de pages

This commit is contained in:
Reto Bollinger 2025-09-01 15:31:07 +02:00
parent 29f23bc3bf
commit 5b023a43f9
10 changed files with 313 additions and 352 deletions

View file

@ -14,4 +14,10 @@ tempfile=$(mktemp)
sh -c ". /opt/venv/bin/activate && exec python /opt/lektor/scripts/calendar-fetcher-main+fr.py ${CALENDAR_URL} > $tempfile" sh -c ". /opt/venv/bin/activate && exec python /opt/lektor/scripts/calendar-fetcher-main+fr.py ${CALENDAR_URL} > $tempfile"
mv $tempfile /opt/lektor/project/content/contents+fr.lr mv $tempfile /opt/lektor/project/content/contents+fr.lr
sh -c ". /opt/venv/bin/activate && exec python /opt/lektor/scripts/calendar-fetcher+de.py ${CALENDAR_URL} > /opt/lektor/project/content/termine/contents+de.lr"
# TODO As the file reads from the same file as it's output is afterwards piped into this leads to synchronization/buffering issues, we therefore write to a temporaray file and move it to the right place in a subsequent step
tempfile=$(mktemp)
sh -c ". /opt/venv/bin/activate && exec python /opt/lektor/scripts/calendar-fetcher-main+de.py ${CALENDAR_URL} > $tempfile"
mv $tempfile /opt/lektor/project/content/contents+de.lr
exec "$@" exec "$@"

View file

@ -0,0 +1,29 @@
_model: htmlpage
---
title: Willkommen beim PC Stammertal
---
html:
<h2>Unser nächster Anlass: </h2><br>
<div class="nextevent">Montag <strong>1. September 18:30, freies Training</strong>, Stammheim</div>
<div>
&nbsp;<br>
&nbsp;<br>
&nbsp;<br>
</div>
<div class="threecolumn">
<div>
<a href="termine/"><img src=" /images/termine_square.jpg" alt="Terminkalender"> All unsere Termine</a>
</div>
<div>
<a href="about/"><img src="/images/about_square.jpg" alt="Buch"> Alle Infos über uns</a>
</div>
<div>
<a href="kontakt/"><img src="/images/kontakt_square.jpg" alt="Briefe"> Kontaktiere uns</a>
</div>
</div>
---
_template:
page.html

View file

@ -5,14 +5,12 @@ title: Bienvenue au PC Stammertal
html: html:
<h2>Notre prochain événement: </h2><br> <h2>Notre prochain événement: </h2><br>
<div class="nextevent">samedi <strong>22. mars 9:00, Frühlingsschiessen</strong>, Bülach</div> <div class="nextevent">lundi <strong>1. septembre 18:30, freies Training</strong>, Stammheim</div>
<div> <div>
&nbsp;<br> &nbsp;<br>
&nbsp;<br> &nbsp;<br>
&nbsp;<br> &nbsp;<br>
</div> </div>
<h3>...et ne manquez pas non plus :</h3>
<a href="https://www.wyland25.ch/" target="_blank"><img src="/images/zhksf.png" alt="27. Zürcher Kantonalschützenfest 2025" class="stamp"></a>
<div class="threecolumn"> <div class="threecolumn">
<div> <div>
<a href="termine/"><img src=" /images/termine_square.jpg" alt="Calendrier"> Tous nos événements</a> <a href="termine/"><img src=" /images/termine_square.jpg" alt="Calendrier"> Tous nos événements</a>

View file

@ -5,14 +5,12 @@ title: Willkommen beim PC Stammertal
html: html:
<h2>Unser nächster Anlass: </h2><br> <h2>Unser nächster Anlass: </h2><br>
<div class="nextevent">Samstag <strong>22. März 9:00, Frühlingsschiessen</strong>, Bülach</div> <div class="nextevent">Montag <strong>1. September 18:30, freies Training</strong>, Stammheim</div>
<div> <div>
&nbsp;<br> &nbsp;<br>
&nbsp;<br> &nbsp;<br>
&nbsp;<br> &nbsp;<br>
</div> </div>
<h3>...und auch nicht verpassen:</h3>
<a href="https://www.wyland25.ch/" target="_blank"><img src="/images/zhksf.png" alt="27. Zürcher Kantonalschützenfest 2025" class="stamp"></a>
<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>

View file

@ -0,0 +1,79 @@
_model: page
---
title: Termine
---
body:
* <div>freies Training</div>&nbsp;
* <div>Mo. 1. September 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Kreismatch</div>&nbsp;
* <div>Mo. 8. September 2025</div>&nbsp;
* <div>18:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Orientierungslauf Stammerberg (kein Schiessbetrieb!)</div>&nbsp;
* <div>Sa. 13. September 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Unterstammheim</div>&nbsp;
* <div>Kreismatch</div>&nbsp;
* <div>Mo. 15. September 2025</div>&nbsp;
* <div>18:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Schwaderlohschiessen</div>&nbsp;
* <div>Sa. 20. September 2025</div>&nbsp;
* <div>13:30</div>&nbsp;
* <div>Alterswilen</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>Mo. 22. September 2025</div>&nbsp;
* <div>18:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Schwaderlohschiessen (unser Schiesstag)</div>&nbsp;
* <div>Di. 23. September 2025</div>&nbsp;
* <div>17:30</div>&nbsp;
* <div>Alterswilen</div>&nbsp;
* <div>Schwaderlohschiessen</div>&nbsp;
* <div>Sa. 27. September 2025</div>&nbsp;
* <div>8:00</div>&nbsp;
* <div>Alterswilen</div>&nbsp;
* <div>Schwaderlohschiessen</div>&nbsp;
* <div>So. 28. September 2025</div>&nbsp;
* <div>10:00</div>&nbsp;
* <div>Alterswilen</div>&nbsp;
* <div>Endschiessen</div>&nbsp;
* <div>Mo. 29. September 2025</div>&nbsp;
* <div>17:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Endschiessen</div>&nbsp;
* <div>Mo. 6. Oktober 2025</div>&nbsp;
* <div>17:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Niklausschiessen</div>&nbsp;
* <div>Sa. 25. Oktober 2025</div>&nbsp;
* <div>9:00</div>&nbsp;
* <div>Diessenhofen</div>&nbsp;
* <div>Niklausschiessen</div>&nbsp;
* <div>So. 26. Oktober 2025</div>&nbsp;
* <div>9:00</div>&nbsp;
* <div>Diessenhofen</div>&nbsp;
* <div>Absenden</div>&nbsp;
* <div>Fr. 31. Oktober 2025</div>&nbsp;
* <div>19:00</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Niklausschiessen</div>&nbsp;
* <div>Sa. 1. November 2025</div>&nbsp;
* <div>9:00</div>&nbsp;
* <div>Diessenhofen</div>&nbsp;
* <div>Appenzeller Lupi Meisterschaft</div>&nbsp;
* <div>So. 11. Januar 2026</div>&nbsp;
* <div>9:00</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Generalversammlung</div>&nbsp;
* <div>Do. 5. Februar 2026</div>&nbsp;
* <div>19:00</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
---
_template: page.html

View file

@ -4,178 +4,6 @@ title: Événements
--- ---
body: body:
* <div>Frühlingsschiessen</div>&nbsp;
* <div>sam. 22. mars 2025</div>&nbsp;
* <div>9:00</div>&nbsp;
* <div>Bülach</div>&nbsp;
* <div>Standreinigung</div>&nbsp;
* <div>sam. 22. mars 2025</div>&nbsp;
* <div>9:00</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>lun. 31. mars 2025</div>&nbsp;
* <div>18:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Eulachschiessen</div>&nbsp;
* <div>ven. 4. avril 2025</div>&nbsp;
* <div>16:00</div>&nbsp;
* <div>Winterthur</div>&nbsp;
* <div>Eulachschiessen</div>&nbsp;
* <div>sam. 5. avril 2025</div>&nbsp;
* <div>8:30</div>&nbsp;
* <div>Winterthur</div>&nbsp;
* <div>Eulachschiessen</div>&nbsp;
* <div>ven. 11. avril 2025</div>&nbsp;
* <div>16:00</div>&nbsp;
* <div>Winterthur</div>&nbsp;
* <div>Eulachschiessen</div>&nbsp;
* <div>sam. 12. avril 2025</div>&nbsp;
* <div>8:30</div>&nbsp;
* <div>Winterthur</div>&nbsp;
* <div>Kreis Winterschiessen</div>&nbsp;
* <div>lun. 14. avril 2025</div>&nbsp;
* <div>18:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Obligatorisches Programm und Kreis Winterschiessen</div>&nbsp;
* <div>lun. 28. avril 2025</div>&nbsp;
* <div>18:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>lun. 5. mai 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>lun. 12. mai 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Schlossschiessen</div>&nbsp;
* <div>jeu. 15. mai 2025</div>&nbsp;
* <div>17:30</div>&nbsp;
* <div>Wülflingen</div>&nbsp;
* <div>Schlossschiessen</div>&nbsp;
* <div>ven. 16. mai 2025</div>&nbsp;
* <div>17:30</div>&nbsp;
* <div>Wülflingen</div>&nbsp;
* <div>Schlossschiessen</div>&nbsp;
* <div>sam. 17. mai 2025</div>&nbsp;
* <div>9:30</div>&nbsp;
* <div>Wülflingen</div>&nbsp;
* <div>Obligatorisches Programm und freies Training</div>&nbsp;
* <div>lun. 19. mai 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Schlossschiessen</div>&nbsp;
* <div>jeu. 22. mai 2025</div>&nbsp;
* <div>17:30</div>&nbsp;
* <div>Wülflingen</div>&nbsp;
* <div>Schlossschiessen</div>&nbsp;
* <div>ven. 23. mai 2025</div>&nbsp;
* <div>17:30</div>&nbsp;
* <div>Wülflingen</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>lun. 26. mai 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Kreis Sommerschiessen</div>&nbsp;
* <div>lun. 2. juin 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Sommer-Schüsse</div>&nbsp;
* <div>ven. 6. juin 2025</div>&nbsp;
* <div>17:00</div>&nbsp;
* <div>Rafz</div>&nbsp;
* <div>Sommer-Schüsse</div>&nbsp;
* <div>sam. 14. juin 2025</div>&nbsp;
* <div>9:00</div>&nbsp;
* <div>Rafz</div>&nbsp;
* <div>Obligatorisches Programm und freies Training</div>&nbsp;
* <div>lun. 16. juin 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>lun. 23. juin 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>lun. 30. juin 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Bezirks Sommerschiessen</div>&nbsp;
* <div>sam. 5. juillet 2025</div>&nbsp;
* <div>17:00</div>&nbsp;
* <div>Flurlingen</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>lun. 7. juillet 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Terassenfest</div>&nbsp;
* <div>ven. 11. juillet 2025</div>&nbsp;
* <div>19:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Bezirks Sommerschiessen</div>&nbsp;
* <div>sam. 12. juillet 2025</div>&nbsp;
* <div>14:00</div>&nbsp;
* <div>Flurlingen</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>lun. 14. juillet 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Obligatorisches Programm und freies Training</div>&nbsp;
* <div>lun. 11. août 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>ZHKSF Ausbildung Pistole</div>&nbsp;
* <div>jeu. 14. août 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>ven. 15. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>sam. 16. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>dim. 17. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>KEIN Training</div>&nbsp;
* <div>lun. 18. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>ZHKSF intern</div>&nbsp;
* <div>jeu. 21. août 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>ven. 22. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>sam. 23. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>dim. 24. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>lun. 25. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>ven. 29. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>sam. 30. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>dim. 31. août 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>freies Training</div>&nbsp; * <div>freies Training</div>&nbsp;
* <div>lun. 1. septembre 2025</div>&nbsp; * <div>lun. 1. septembre 2025</div>&nbsp;
* <div>18:30</div>&nbsp; * <div>18:30</div>&nbsp;

View file

@ -4,178 +4,6 @@ title: Termine
--- ---
body: body:
* <div>Frühlingsschiessen</div>&nbsp;
* <div>Sa. 22. März 2025</div>&nbsp;
* <div>9:00</div>&nbsp;
* <div>Bülach</div>&nbsp;
* <div>Standreinigung</div>&nbsp;
* <div>Sa. 22. März 2025</div>&nbsp;
* <div>9:00</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>Mo. 31. März 2025</div>&nbsp;
* <div>18:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Eulachschiessen</div>&nbsp;
* <div>Fr. 4. April 2025</div>&nbsp;
* <div>16:00</div>&nbsp;
* <div>Winterthur</div>&nbsp;
* <div>Eulachschiessen</div>&nbsp;
* <div>Sa. 5. April 2025</div>&nbsp;
* <div>8:30</div>&nbsp;
* <div>Winterthur</div>&nbsp;
* <div>Eulachschiessen</div>&nbsp;
* <div>Fr. 11. April 2025</div>&nbsp;
* <div>16:00</div>&nbsp;
* <div>Winterthur</div>&nbsp;
* <div>Eulachschiessen</div>&nbsp;
* <div>Sa. 12. April 2025</div>&nbsp;
* <div>8:30</div>&nbsp;
* <div>Winterthur</div>&nbsp;
* <div>Kreis Winterschiessen</div>&nbsp;
* <div>Mo. 14. April 2025</div>&nbsp;
* <div>18:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Obligatorisches Programm und Kreis Winterschiessen</div>&nbsp;
* <div>Mo. 28. April 2025</div>&nbsp;
* <div>18:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>Mo. 5. Mai 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>Mo. 12. Mai 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Schlossschiessen</div>&nbsp;
* <div>Do. 15. Mai 2025</div>&nbsp;
* <div>17:30</div>&nbsp;
* <div>Wülflingen</div>&nbsp;
* <div>Schlossschiessen</div>&nbsp;
* <div>Fr. 16. Mai 2025</div>&nbsp;
* <div>17:30</div>&nbsp;
* <div>Wülflingen</div>&nbsp;
* <div>Schlossschiessen</div>&nbsp;
* <div>Sa. 17. Mai 2025</div>&nbsp;
* <div>9:30</div>&nbsp;
* <div>Wülflingen</div>&nbsp;
* <div>Obligatorisches Programm und freies Training</div>&nbsp;
* <div>Mo. 19. Mai 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Schlossschiessen</div>&nbsp;
* <div>Do. 22. Mai 2025</div>&nbsp;
* <div>17:30</div>&nbsp;
* <div>Wülflingen</div>&nbsp;
* <div>Schlossschiessen</div>&nbsp;
* <div>Fr. 23. Mai 2025</div>&nbsp;
* <div>17:30</div>&nbsp;
* <div>Wülflingen</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>Mo. 26. Mai 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Kreis Sommerschiessen</div>&nbsp;
* <div>Mo. 2. Juni 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Sommer-Schüsse</div>&nbsp;
* <div>Fr. 6. Juni 2025</div>&nbsp;
* <div>17:00</div>&nbsp;
* <div>Rafz</div>&nbsp;
* <div>Sommer-Schüsse</div>&nbsp;
* <div>Sa. 14. Juni 2025</div>&nbsp;
* <div>9:00</div>&nbsp;
* <div>Rafz</div>&nbsp;
* <div>Obligatorisches Programm und freies Training</div>&nbsp;
* <div>Mo. 16. Juni 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>Mo. 23. Juni 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>Mo. 30. Juni 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Bezirks Sommerschiessen</div>&nbsp;
* <div>Sa. 5. Juli 2025</div>&nbsp;
* <div>17:00</div>&nbsp;
* <div>Flurlingen</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>Mo. 7. Juli 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Terassenfest</div>&nbsp;
* <div>Fr. 11. Juli 2025</div>&nbsp;
* <div>19:00</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Bezirks Sommerschiessen</div>&nbsp;
* <div>Sa. 12. Juli 2025</div>&nbsp;
* <div>14:00</div>&nbsp;
* <div>Flurlingen</div>&nbsp;
* <div>freies Training</div>&nbsp;
* <div>Mo. 14. Juli 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>Obligatorisches Programm und freies Training</div>&nbsp;
* <div>Mo. 11. August 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>Stammheim</div>&nbsp;
* <div>ZHKSF Ausbildung Pistole</div>&nbsp;
* <div>Do. 14. August 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>Fr. 15. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>Sa. 16. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>So. 17. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>KEIN Training</div>&nbsp;
* <div>Mo. 18. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>ZHKSF intern</div>&nbsp;
* <div>Do. 21. August 2025</div>&nbsp;
* <div>18:30</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>Fr. 22. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>Sa. 23. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>So. 24. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>Mo. 25. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>Fr. 29. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>Sa. 30. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>Zürcher Kantonalschützenfest</div>&nbsp;
* <div>So. 31. August 2025</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>&nbsp;</div>&nbsp;
* <div>freies Training</div>&nbsp; * <div>freies Training</div>&nbsp;
* <div>Mo. 1. September 2025</div>&nbsp; * <div>Mo. 1. September 2025</div>&nbsp;
* <div>18:30</div>&nbsp; * <div>18:30</div>&nbsp;

View file

@ -0,0 +1,57 @@
from datetime import datetime, date, timezone
import locale
import sys
from calendarstuff import get_events
def fetch_upcoming_events(ics_url):
events = get_events(ics_url, 'de_DE.UTF-8')
for event in events:
start = event.get('dtstart').dt
out_summary = event.get('summary')
location = event.get('location', 'No location specified')
out_startdate = start.strftime("%a. %-d. %B %Y")
# Format output based on whether it's an all-day event
if isinstance(start, date) and not isinstance(start, datetime):
out_starttime = "&nbsp;"
else:
out_starttime = start.strftime('%-H:%M')
if location != 'No location specified':
out_location = location
else:
out_location = "&nbsp;"
print(f"* <div>{out_summary}</div>&nbsp;")
print(f" * <div>{out_startdate}</div>&nbsp;")
print(f" * <div>{out_starttime}</div>&nbsp;")
print(f" * <div>{out_location}</div>&nbsp;")
if __name__ == "__main__":
ics_url = sys.argv[1]
# ics_url = "https://backoffice.pc-stammertal.ch/remote.php/dav/public-calendars/RqLX5wj25aY6cpnP?export"
print("_model: page")
print("---")
print("title: Termine")
print("---")
print("body:")
print("")
# print("<center><a href=\"https://backoffice.pc-stammertal.ch/remote.php/dav/public-calendars/RqLX5wj25aY6cpnP?export\">Kalender Abonnieren</a></center>")
# print("")
# print("<center><a href=\"https://backoffice.pc-stammertal.ch/remote.php/dav/public-calendars/RqLX5wj25aY6cpnP?export\"><img src=\"/images/calendar.png\" alt=\"Link als QR code\"></a></center>")
# print("")
fetch_upcoming_events(ics_url)
print("")
print("---")
print("_template: page.html")
print("")
print("")

View file

@ -0,0 +1,140 @@
#!/usr/bin/env python3
import sys
from pathlib import Path
from datetime import datetime, date, timezone
from typing import Optional, NamedTuple
from dataclasses import dataclass
from bs4 import BeautifulSoup
import locale
from calendarstuff import get_events
@dataclass
class EventDetails:
weekday: str
date: str
time: str
summary: str
location: str
def to_html(self) -> str:
return (
f'<div class="nextevent">{self.weekday} '
f'<strong>{self.date}{self.time}, {self.summary}</strong>'
f'{self.location}</div>'
)
class EventProcessor:
def __init__(self, ics_url: str, content_file: str):
self.ics_url = ics_url
self.content_file = Path(content_file)
self.fallback_html = (
'<div class="nextevent">Leider unbekannt, aber '
'<strong>frag mal den Vorstand</strong> der müsste es wissen</div>'
)
@property
def fallback_content(self) -> str:
return f"""_model: htmlpage
---
title: Willkommen beim PC Stammertal
---
html:
<h2>Unser nächster Anlass: </h2><br>
{self.fallback_html}
<div>
&nbsp;<br>
&nbsp;<br>
&nbsp;<br>
</div>
<div class="threecolumn">
<div>
<a href="termine/"><img src=" /images/termine_square.jpg" alt="Terminkalender"> All unsere Termine</a>
</div>
<div>
<a href="about/"><img src="/images/about_square.jpg" alt="Buch"> Alle Infos über uns</a>
</div>
<div>
<a href="kontakt/"><img src="/images/kontakt_square.jpg" alt="Briefe"> Kontaktiere uns</a>
</div>
</div>
---
_template:
page.html
"""
def setup_locale(self) -> None:
try:
locale.setlocale(locale.LC_TIME, 'de_DE.UTF-8')
except locale.Error as e:
print(f"Warning: Failed to set locale: {e}", file=sys.stderr)
def format_event_time(self, start: datetime | date) -> str:
return "" if isinstance(start, date) and not isinstance(start, datetime) else start.strftime(" %-H:%M")
def get_next_event(self) -> Optional[EventDetails]:
try:
events = get_events(self.ics_url, 'de_DE.UTF-8')
event = events[0]
start = event.get('dtstart').dt
return EventDetails(
weekday=start.strftime("%A"),
date=start.strftime("%-d. %B"),
time=self.format_event_time(start),
summary=event.get('summary', ''),
location=f", {event.get('location')}" if event.get('location') else ""
)
except (StopIteration, AttributeError) as e:
print(f"No upcoming events found: {e}", file=sys.stderr)
return None
def read_current_content(self) -> tuple[str, str]:
try:
content = self.content_file.read_text()
soup = BeautifulSoup(content, 'html.parser')
events = soup.find_all('div', {'class': 'nextevent'})
return content, str(events[0]) if len(events) == 1 else ""
except (IOError, IndexError) as e:
print(f"Error reading content file: {e}", file=sys.stderr)
return "", ""
def process(self) -> str:
self.setup_locale()
content, source_str = self.read_current_content()
if not content:
return self.fallback_content
if len(source_str) > 0 and source_str in content:
event = self.get_next_event()
if not event:
return content.replace(source_str, self.fallback_html).rstrip()
return content.replace(source_str, event.to_html()).rstrip()
return self.fallback_content
def main() -> None:
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <ICS_URL>", file=sys.stderr)
sys.exit(1)
processor = EventProcessor(
ics_url=sys.argv[1],
content_file="/opt/lektor/project/content/contents+de.lr"
)
print(processor.process(), end='')
print("")
print("")
if __name__ == "__main__":
main()

View file

@ -49,8 +49,6 @@ html:
&nbsp;<br> &nbsp;<br>
&nbsp;<br> &nbsp;<br>
</div> </div>
<h3>...et ne manquez pas non plus :</h3>
<a href="https://www.wyland25.ch/" target="_blank"><img src="/images/zhksf.png" alt="27. Zürcher Kantonalschützenfest 2025" class="stamp"></a>
<div class="threecolumn"> <div class="threecolumn">
<div> <div>
<a href="termine/"><img src=" /images/termine_square.jpg" alt="Calendrier"> Tous nos événements</a> <a href="termine/"><img src=" /images/termine_square.jpg" alt="Calendrier"> Tous nos événements</a>