epaper/modules/ical.py

81 lines
2.8 KiB
Python
Raw Normal View History

2022-08-14 17:51:51 +00:00
from datetime import datetime, timedelta, timezone
2022-08-19 14:59:00 +00:00
import hashlib
import urllib.error
2022-08-14 17:51:51 +00:00
import urllib.request
from icalendar import Calendar, Event, vCalAddress, vText
from PIL import Image, ImageDraw, ImageFont
import pytz
class IcalModule:
2022-08-14 17:55:12 +00:00
def __init__(self, config):
self.cals = config.cals
2022-08-14 17:51:51 +00:00
2022-08-19 14:59:00 +00:00
self._cached_file = ".ical-%s.cache"
self.cache_time = 15
2022-08-14 17:51:51 +00:00
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:
2022-08-19 14:59:00 +00:00
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:
2022-08-14 17:51:51 +00:00
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