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 import dateutil.parser from dotenv import load_dotenv black = '#000000' white = '#ffffff' fontSymbols = ImageFont.truetype("SymbolsNerdFont-Regular.ttf", 18) fontTitle = ImageFont.truetype("Nunito-SemiBold.ttf", 24) fontLarge = ImageFont.truetype ("Nunito-ExtraLight.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 draw.rectangle((0, 0, 400, 300), fill=white) draw.rectangle((0, 0, 400, 30), fill=black) # Add the clock timeStr = strftime("%H:%M", time.localtime()) draw.text((10, 5), timeStr, white, fontSmall) # Add indoor tempriture draw.text((350, 5), "19c", white, fontSmall) # Add sections ep = 5 draw.rounded_rectangle((ep, 30+ep, (400/2)-ep, 300-ep), 10, outline=black, width=2) draw.rounded_rectangle(((400/2) + ep, 30+ep, 400-ep, 300-ep), 10, outline=black, width=2) # Add tasks draw.text((15, 40), 'Tasks', black, fontTitle) tasks = [ {'done': False, 'title': 'Something'}, {'done': True, 'title': 'Get the Modus and Audi MOTs organised'}, {'done': False, 'title': 'Something else'}, {'done': False, 'title': 'Call locksmith'}, ] taskStart = 80 for task in tasks: if task['done']: draw.text((15, taskStart-2), '󰄵', black, fontSymbols) else: draw.text((15, taskStart-2), '󰄱', black, fontSymbols) reflowedTitle = reflow_quote(task['title'], 170, 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((215, 40), 'Calendar', black, fontTitle) 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 = 80 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, fontLarge) 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')