diff --git a/.gitignore b/.gitignore index c18dd8d..c9e9e82 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ + +# Program state +config.py +calendar.sqlite + +# Python __pycache__/ diff --git a/google_calendar.py b/google_calendar.py new file mode 100644 index 0000000..0b6baf1 --- /dev/null +++ b/google_calendar.py @@ -0,0 +1,32 @@ + +import functools +import requests_cache +from ical.calendar_stream import IcsCalendarStream +import datetime +import logging + +logger = logging.getLogger(__name__) + +SESSION = requests_cache.CachedSession('calendar') + +@functools.cache +def get_events_for_month(ical_link, today): + logger.warning('Downloading ical from Google') + response = SESSION.get(ical_link) + assert response.status_code == 200 + + logger.warning('Loading ical') + calendar = IcsCalendarStream.calendar_from_ics(response.text) + + today = datetime.date.today() + + logger.warning('Iterating ical') + date = today.replace(day = 1) + stuff = [] + while date.month == today.month: + for e in calendar.timeline.on_date(date): + stuff.append((date, e)) + + date += datetime.timedelta(days = 1) + return stuff + diff --git a/main.py b/main.py index 85d01c4..6705a82 100644 --- a/main.py +++ b/main.py @@ -1,30 +1,43 @@ import argparse import bottle +import datetime + +import google_calendar + +import config TEMPLATE_INDEX = bottle.SimpleTemplate(name = "templates/index.html") -# - -def determine_data(): - pass - # Template rendering +def last_day_of_month(date): + date = date.replace(day = 28) + datetime.timedelta(days = 5) + date = date.replace(day = 1) + date = date - datetime.timedelta(days = 1) + return date + +def range_to_render(today): + first_day_of_month = today.replace(day = 1) + start = first_day_of_month - datetime.timedelta(days = first_day_of_month.weekday()) + end = last_day_of_month(today) + return (start, end) + def render_calendar(events_map, today): days = [] - for day_of_month in range(1, 31 + 1): - day_of_week = (day_of_month - 1) % 7 + 1 - week_of_year = day_of_month // 7 + 1 + start, end = range_to_render(today) + date = start + while date <= end: days.append({ - 'day_of_month': day_of_month, - 'day_of_week': day_of_week, - 'is_weekend': day_of_week == 6 or day_of_week == 7, - 'week_of_year' : week_of_year, - 'today': day_of_month == today, - 'already_past': day_of_month < today, - 'events': events_map.get(day_of_month, []), + 'date': date, + 'is_weekend': date.isoweekday() == 6 or date.isoweekday() == 7, + 'week_of_year': int(date.strftime('%W')), + 'days_from_now': (date - today).days, + 'events': events_map.get(date, []), }) - return TEMPLATE_INDEX.render(days = days) + date += datetime.timedelta(days = 1) + + header = today.strftime('%B %Y') + return TEMPLATE_INDEX.render(days = days, header = header) ## Paths @@ -32,16 +45,20 @@ def render_calendar(events_map, today): def static(path): return bottle.static_file(path, root = './static') +def get_events_map(): + today = datetime.date.today() + events_map = { } + for prefix, url in config.ICAL_LINKS.items(): + for date, event in google_calendar.get_events_for_month(url, today): + text = '{}: {}'.format(prefix, event.summary) + events_map.setdefault(date, []).append(text) + del date, event, text + + return events_map, today + @bottle.route('/') def reddit_index(): - events_map = { - 15: ['J: Japansk 1'], - 19: ['J: Spil Fredagsbar', 'L: Datbar'], - 20: ['JL: Regatta'], - } - - today = 19 - + events_map, today = get_events_map() return render_calendar(events_map, today) ## Argument parsing diff --git a/templates/index.html b/templates/index.html index 74c006a..acc49c5 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,12 +1,14 @@ - My calendar + {{ header }} + -

August 2022

+

{{ header }}

@@ -23,7 +25,7 @@ % for day_info in days: -% if day_info['day_of_week'] == 1: +% if day_info['date'].isoweekday() == 1: @@ -32,14 +34,14 @@ % if day_info['is_weekend']: weekend-day % end -% if day_info['already_past']: +% if day_info['days_from_now'] < 0: crossed-out % end ">
{{ day_info['day_of_month'] }}
+ ">{{ day_info['date'].day }} % for event_text in day_info['events']:
{{ event_text }}
% end
W{{ day_info['week_of_year'] }}