163 lines
4.6 KiB
Python
163 lines
4.6 KiB
Python
from PIL import Image
|
|
from PIL import ImageDraw
|
|
from PIL import ImageFont
|
|
from datetime import datetime, timedelta
|
|
from time import gmtime, strftime
|
|
import time
|
|
from itertools import groupby
|
|
from hasApi import get_calendar_events, get_todo_items
|
|
import dateutil.parser
|
|
from dotenv import load_dotenv
|
|
|
|
black = "#000000"
|
|
white = "#ffffff"
|
|
|
|
|
|
fontSymbols = ImageFont.truetype("SymbolsNerdFont-Regular.ttf", 18)
|
|
fontTitle = ImageFont.truetype("Nunito-Bold.ttf", 24)
|
|
fontLarge = ImageFont.truetype("Nunito-ExtraLight.ttf", 18)
|
|
fontLargeBold = ImageFont.truetype("Nunito-SemiBold.ttf", 18)
|
|
fontSmall = ImageFont.truetype("Nunito-ExtraLight.ttf", 16)
|
|
fontVerySmall = ImageFont.truetype("Nunito-ExtraLight.ttf", 10)
|
|
|
|
|
|
class Space(Exception):
|
|
pass
|
|
|
|
|
|
def getsize(font, text):
|
|
_, _, right, bottom = font.getbbox(text)
|
|
return (right, bottom)
|
|
|
|
|
|
def reflow_quote(quote, width, font):
|
|
words = quote.split(" ")
|
|
reflowed = ""
|
|
line_length = 0
|
|
|
|
for i in range(len(words)):
|
|
word = words[i] + " "
|
|
word_length = getsize(font, word)[0]
|
|
line_length += word_length
|
|
|
|
if line_length < width:
|
|
reflowed += word
|
|
else:
|
|
line_length = word_length
|
|
reflowed = reflowed[:-1] + "\n " + word
|
|
|
|
reflowed = reflowed.rstrip()
|
|
|
|
return reflowed
|
|
|
|
|
|
def draw_image():
|
|
image = Image.new("P", (400, 300))
|
|
draw = ImageDraw.Draw(image)
|
|
|
|
# Draw the top bar
|
|
topbar = 26
|
|
draw.rectangle((0, 0, 400, 300), fill=white)
|
|
draw.rectangle((0, 0, 400, topbar), fill=black)
|
|
|
|
# Add the clock
|
|
timeStr = strftime("%H:%M", time.localtime())
|
|
draw.text((10, 3), timeStr, white, fontSmall)
|
|
|
|
# Add indoor temperature
|
|
draw.text((350, 3), "19c", white, fontSmall)
|
|
|
|
# Add sections
|
|
ep = 3
|
|
margin = 5
|
|
draw.rounded_rectangle(
|
|
(margin, topbar + margin, (400 / 2) - margin, 300 - margin),
|
|
10,
|
|
outline=black,
|
|
width=2,
|
|
)
|
|
draw.rounded_rectangle(
|
|
((400 / 2) + margin, topbar + margin, 400 - margin, 300 - margin),
|
|
10,
|
|
outline=black,
|
|
width=2,
|
|
)
|
|
|
|
# Add tasks
|
|
draw.text((20, topbar + 7), "Tasks", black, fontTitle)
|
|
draw.line((margin, 62, 200 - margin, 62), fill=black, width=1)
|
|
|
|
tasks = get_todo_items()
|
|
|
|
taskStart = 70
|
|
for task in tasks:
|
|
if task["status"] == "completed":
|
|
continue
|
|
draw.text((15, taskStart - 2), "", black, fontSymbols)
|
|
else:
|
|
draw.text((15, taskStart), "", black, fontSymbols)
|
|
|
|
reflowedTitle = reflow_quote(task["summary"], 160, fontLarge)
|
|
titleSizeW, titleSizeH = getsize(fontLarge, reflowedTitle)
|
|
titleSizeH *= reflowedTitle.count("\n") + 1
|
|
|
|
draw.text((35, taskStart - 3), reflowedTitle, black, fontLarge)
|
|
taskStart += titleSizeH + (2 * ep)
|
|
|
|
# Add cal
|
|
draw.text((220, topbar + 7), "Calendar", black, fontTitle)
|
|
draw.line(((400 / 2) + margin, 62, 400 - margin, 62), fill=black, width=1)
|
|
events = get_calendar_events()
|
|
|
|
def get_start_date(x):
|
|
start = x["start"]
|
|
if "date" in start:
|
|
startDate = datetime.strptime(start["date"], "%Y-%m-%d").date()
|
|
elif "dateTime" in start:
|
|
startDate = datetime.strptime(start["dateTime"][:10], "%Y-%m-%d").date()
|
|
else:
|
|
print("Error")
|
|
print(start)
|
|
return None
|
|
if startDate < datetime.today().date():
|
|
return datetime.today().date()
|
|
else:
|
|
return startDate
|
|
|
|
itemStart = 70
|
|
try:
|
|
for key, group in groupby(events, get_start_date):
|
|
if key == datetime.today().date():
|
|
dateStr = "Today"
|
|
elif key == (datetime.today() + timedelta(days=1)).date():
|
|
dateStr = "Tomorrow"
|
|
else:
|
|
dateStr = key.strftime("%d %b")
|
|
|
|
draw.text((215, itemStart), dateStr, black, fontLargeBold)
|
|
w, h = getsize(fontLarge, "Today")
|
|
itemStart += h + (ep)
|
|
|
|
for thing in list(group):
|
|
reflowedItem = reflow_quote(thing["summary"], 170, fontSmall)
|
|
w, h = getsize(fontLarge, "Today")
|
|
h *= reflowedItem.count("\n") + 1
|
|
# print(f'After {reflowedItem}, {itemStart + h}')
|
|
if itemStart + h > 270:
|
|
raise Space
|
|
draw.text((230, itemStart), reflowedItem, black, fontSmall)
|
|
itemStart += h + (ep)
|
|
|
|
if itemStart > 250:
|
|
raise Space
|
|
except Space:
|
|
pass
|
|
|
|
return image
|
|
|
|
|
|
if __name__ == "__main__":
|
|
load_dotenv()
|
|
img = draw_image()
|
|
img.save("built.bmp")
|