diff --git a/main.py b/main.py index 3c7aab3..0e531cd 100644 --- a/main.py +++ b/main.py @@ -69,6 +69,11 @@ def main(): ratp = RATPWeatherModule().draw_module(config, int(480/1.6), 94) image.paste(ratp, (480-int(480/1.6), 155)) + # ical + from modules.ical import IcalModule + cal = IcalModule().draw_module(config, 480-int(480/1.6), 255) + image.paste(cal, (0, 250)) + # Toolbar from modules.weather import WeatherToolbarModule image.paste(WeatherToolbarModule().draw_module(config, 480, 50), (0, 530)) diff --git a/modules/ical.py b/modules/ical.py new file mode 100644 index 0000000..c036107 --- /dev/null +++ b/modules/ical.py @@ -0,0 +1,64 @@ +from datetime import datetime, timedelta, timezone +import urllib.request + +from icalendar import Calendar, Event, vCalAddress, vText +from PIL import Image, ImageDraw, ImageFont +import pytz + +class IcalModule: + + def __init__(self, cals=[]): + self.cals = cals + + def draw_module(self, config, width, height, line_height=19): + now = datetime.now(tz=pytz.timezone('Europe/Paris')) + toofar = now + timedelta(weeks=1) + + events = [] + for cal in self.cals: + with urllib.request.urlopen(cal) as c: + ecal = Calendar.from_ical(c.read()) + for component in ecal.walk(): + if component.name == "VEVENT": + if component.decoded("DTEND") < now: + continue + if component.decoded("DTSTART") > toofar: + continue + + events.append({ + "summary": component.get("SUMMARY"), + "start": component.decoded("DTSTART"), + "end": component.decoded("DTEND"), + }) + + # Sort events + events.sort(key=lambda e: e["start"]) + + image = Image.new('RGB', (width, height), '#fff') + draw = ImageDraw.Draw(image) + + fnt_R = ImageFont.truetype(config.fnt_R_path, int(line_height*0.7)) + fnt_B = ImageFont.truetype(config.fnt_RB_path, int(line_height*0.7)) + + last_evt = None + align = 0 + for evt in events: + if last_evt is None or last_evt["start"].astimezone(pytz.timezone('Europe/Paris')).day != evt["start"].astimezone(pytz.timezone('Europe/Paris')).day: + draw.text( + (width / 2, align), + evt["start"].astimezone(pytz.timezone('Europe/Paris')).strftime("%a %d %B"), + fill="black", anchor="mt", font=fnt_B + ) + align += line_height + draw.rectangle((0, align-4, width, align-4), fill="black") + + draw.text( + (2, align), + evt["start"].astimezone(pytz.timezone('Europe/Paris')).strftime("%H:%M") + " " + evt["summary"], + fill="black", anchor="lt", font=fnt_R + ) + + align += line_height + last_evt = evt + + return image