epaper/modules/ical.py

65 lines
2.3 KiB
Python

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