forked from cccb-website-team/www
Merge branch 'main-staging' into staging
This commit is contained in:
commit
75ae1c30a2
35 changed files with 10781 additions and 761 deletions
|
|
@ -1,108 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import html
|
||||
import logging
|
||||
import locale
|
||||
from datetime import datetime, timedelta, timezone, date
|
||||
from dateutil.rrule import rruleset, rrulestr
|
||||
|
||||
import icalendar
|
||||
|
||||
|
||||
def _to_aware(dt):
|
||||
"""Normalize a date or datetime to a timezone-aware UTC datetime."""
|
||||
if isinstance(dt, date) and not isinstance(dt, datetime):
|
||||
return datetime(dt.year, dt.month, dt.day, tzinfo=timezone.utc)
|
||||
if dt.tzinfo is None:
|
||||
return dt.replace(tzinfo=timezone.utc)
|
||||
return dt.astimezone(timezone.utc)
|
||||
|
||||
|
||||
def vevent_to_event(event, rrstart=None):
|
||||
if rrstart is None:
|
||||
begin = _to_aware(event["DTSTART"].dt)
|
||||
else:
|
||||
begin = _to_aware(rrstart)
|
||||
|
||||
return {
|
||||
"name": str(event.get("SUMMARY", "")),
|
||||
"url": str(event.get("URL", "")),
|
||||
"begin": begin
|
||||
}
|
||||
|
||||
|
||||
def parse_single_event(event, start, end):
|
||||
logging.info(f"Processing single event {event.get('SUMMARY', '')}")
|
||||
dtstart = _to_aware(event["DTSTART"].dt)
|
||||
if dtstart >= start and dtstart < end:
|
||||
return vevent_to_event(event)
|
||||
|
||||
|
||||
def parse_recurring_event(event, start, end):
|
||||
logging.info(f"Processing recurring event {event.get('SUMMARY', '')}")
|
||||
dtstart = _to_aware(event["DTSTART"].dt)
|
||||
rs = rruleset()
|
||||
rs.rrule(rrulestr(event["RRULE"].to_ical().decode("utf-8"), dtstart=dtstart))
|
||||
if "EXDATE" in event.keys():
|
||||
exdates = event["EXDATE"]
|
||||
if not isinstance(exdates, list):
|
||||
exdates = [exdates]
|
||||
for exdate_list in exdates:
|
||||
for dt in exdate_list.dts:
|
||||
rs.exdate(_to_aware(dt.dt))
|
||||
|
||||
events = []
|
||||
for dt in rs.between(start, end, inc=True):
|
||||
events.append(vevent_to_event(event, dt))
|
||||
|
||||
return events
|
||||
|
||||
|
||||
def find_events(icsfilestr, start, end, num):
|
||||
with open(icsfilestr, "r") as icsfile:
|
||||
cal = icalendar.Calendar.from_ical(icsfile.read())
|
||||
|
||||
events = []
|
||||
for event in cal.subcomponents:
|
||||
if event.name == "VEVENT":
|
||||
if "RRULE" in event.keys():
|
||||
events.extend(parse_recurring_event(event, start, end))
|
||||
else:
|
||||
ev = parse_single_event(event, start, end)
|
||||
if ev is not None:
|
||||
events.append(ev)
|
||||
|
||||
events = sorted(events, key=lambda k: k["begin"])
|
||||
events = events[0:num]
|
||||
|
||||
return events
|
||||
|
||||
|
||||
def format_events(events):
|
||||
print("<table class=\"table table-condensed\">")
|
||||
for event in events:
|
||||
name = html.escape(event['name'])
|
||||
url = html.escape(event['url'])
|
||||
print(
|
||||
"<tr>"
|
||||
f"<td>{event['begin'].strftime('%A, %d.%m um %H:%M Uhr')}</td>"
|
||||
f"<td><a href=\"{url}\">{name}</a></td>"
|
||||
"</tr>"
|
||||
)
|
||||
print("</table><!--/.table .table-condensed-->")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 4:
|
||||
print(f"Usage: {sys.argv[0]} calendar max_days max_items")
|
||||
sys.exit(1)
|
||||
|
||||
locale.setlocale(locale.LC_TIME, "de_DE.UTF-8")
|
||||
calendar = sys.argv[1]
|
||||
max_days = int(sys.argv[2])
|
||||
max_items = int(sys.argv[3])
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
events = find_events(calendar, now, now + timedelta(days=max_days), max_items)
|
||||
format_events(events)
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import logging
|
||||
from glob import glob
|
||||
|
||||
import icalendar
|
||||
|
||||
|
||||
calendars = []
|
||||
merged = icalendar.Calendar()
|
||||
merged.add("prodid", "-//CCCB Calendar Generator//berlin.ccc.de//")
|
||||
merged.add("version", "2.0")
|
||||
|
||||
for icsfilestr in glob("public/*/**/*.ics", recursive=True):
|
||||
try:
|
||||
with open(icsfilestr, "r") as icsfile:
|
||||
print(f"Importing {icsfilestr}")
|
||||
calendars.append(icalendar.Calendar.from_ical(icsfile.read()))
|
||||
except Exception as e:
|
||||
logging.warning(f"Skipping {icsfilestr}: {e}")
|
||||
|
||||
for calendar in calendars:
|
||||
for event in calendar.subcomponents:
|
||||
if event.name != "VEVENT":
|
||||
continue
|
||||
if "DTSTART" not in event:
|
||||
continue
|
||||
merged.add_component(event)
|
||||
|
||||
outfile = "static/all.ics"
|
||||
with open(outfile, "wb") as f:
|
||||
print(f"writing to {outfile}...")
|
||||
f.write(merged.to_ical())
|
||||
|
||||
Loading…
Reference in a new issue