epaper/modules/ical.py

81 lines
2.8 KiB
Python

from datetime import datetime, timedelta, timezone
import hashlib
import urllib.error
import urllib.request
from icalendar import Calendar, Event, vCalAddress, vText
from PIL import Image, ImageDraw, ImageFont
import pytz
class IcalModule:
def __init__(self, config):
self.cals = config.cals
self._cached_file = ".ical-%s.cache"
self.cache_time = 15
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:
cache_file = self._cached_file % (hashlib.md5(cal.encode()).hexdigest())
try:
with urllib.request.urlopen(cal) as c:
with open(cache_file, 'wb') as fd:
fd.write(c.read())
except ConnectionResetError:
pass
except urllib.error.URLError:
pass
with open(cache_file) 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