Todo items from HAS

This commit is contained in:
2025-02-16 20:19:55 +00:00
parent 8758248fea
commit 018643dde9
4 changed files with 112 additions and 57 deletions

14
README.md Normal file
View File

@@ -0,0 +1,14 @@
## Installation
```bash
sudo apt update
sudo apt install python3-pip
git clone https://github.com/pimoroni/inky
cd inky
./install.sh
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

View File

@@ -5,29 +5,34 @@ from datetime import datetime, timedelta
from time import gmtime, strftime from time import gmtime, strftime
import time import time
from itertools import groupby from itertools import groupby
from hasApi import get_calendar_events from hasApi import get_calendar_events, get_todo_items
import dateutil.parser import dateutil.parser
from dotenv import load_dotenv from dotenv import load_dotenv
black = '#000000' black = "#000000"
white = '#ffffff' white = "#ffffff"
fontSymbols = ImageFont.truetype("SymbolsNerdFont-Regular.ttf", 18) fontSymbols = ImageFont.truetype("SymbolsNerdFont-Regular.ttf", 18)
fontTitle = ImageFont.truetype("Nunito-SemiBold.ttf", 24) fontTitle = ImageFont.truetype("Nunito-SemiBold.ttf", 24)
fontLarge = ImageFont.truetype("Nunito-ExtraLight.ttf", 18) fontLarge = ImageFont.truetype("Nunito-ExtraLight.ttf", 18)
fontLargeBold = ImageFont.truetype("Nunito-SemiBold.ttf", 18)
fontSmall = ImageFont.truetype("Nunito-ExtraLight.ttf", 16) fontSmall = ImageFont.truetype("Nunito-ExtraLight.ttf", 16)
fontVerySmall = ImageFont.truetype("Nunito-ExtraLight.ttf", 10) fontVerySmall = ImageFont.truetype("Nunito-ExtraLight.ttf", 10)
class Space(Exception): pass
class Space(Exception):
pass
def getsize(font, text): def getsize(font, text):
_, _, right, bottom = font.getbbox(text) _, _, right, bottom = font.getbbox(text)
return (right, bottom) return (right, bottom)
def reflow_quote(quote, width, font): def reflow_quote(quote, width, font):
words = quote.split(" ") words = quote.split(" ")
reflowed = '' reflowed = ""
line_length = 0 line_length = 0
for i in range(len(words)): for i in range(len(words)):
@@ -45,6 +50,7 @@ def reflow_quote(quote, width, font):
return reflowed return reflowed
def draw_image(): def draw_image():
image = Image.new("P", (400, 300)) image = Image.new("P", (400, 300))
draw = ImageDraw.Draw(image) draw = ImageDraw.Draw(image)
@@ -61,82 +67,86 @@ def draw_image():
draw.text((350, 5), "19c", white, fontSmall) draw.text((350, 5), "19c", white, fontSmall)
# Add sections # Add sections
ep = 5 ep = 3
draw.rounded_rectangle((ep, 30+ep, (400/2)-ep, 300-ep), 10, outline=black, width=2) draw.rounded_rectangle(
draw.rounded_rectangle(((400/2) + ep, 30+ep, 400-ep, 300-ep), 10, outline=black, width=2) (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 # Add tasks
draw.text((15, 40), 'Tasks', black, fontTitle) draw.text((15, 40), "Tasks", black, fontTitle)
tasks = [ tasks = get_todo_items()
{'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 taskStart = 80
for task in tasks: for task in tasks:
if task['done']: if task["status"] == "completed":
draw.text((15, taskStart-2), '󰄵', black, fontSymbols) continue
draw.text((15, taskStart - 2), "󰄵", black, fontSymbols)
else: else:
draw.text((15, taskStart-2), '󰄱', black, fontSymbols) draw.text((15, taskStart), "󰄱", black, fontSymbols)
reflowedTitle = reflow_quote(task['title'], 170, fontLarge) reflowedTitle = reflow_quote(task["summary"], 160, fontLarge)
titleSizeW, titleSizeH = getsize(fontLarge, reflowedTitle) titleSizeW, titleSizeH = getsize(fontLarge, reflowedTitle)
titleSizeH *= (reflowedTitle.count('\n') + 1) titleSizeH *= reflowedTitle.count("\n") + 1
draw.text((35, taskStart - 3), reflowedTitle, black, fontLarge) draw.text((35, taskStart - 3), reflowedTitle, black, fontLarge)
taskStart += titleSizeH + (2 * ep) taskStart += titleSizeH + (2 * ep)
# Add cal # Add cal
draw.text((215, 40), 'Calendar', black, fontTitle) draw.text((215, 40), "Calendar", black, fontTitle)
events = get_calendar_events() events = get_calendar_events()
def get_start_date(x): def get_start_date(x):
start = x['start'] start = x["start"]
if 'date' in start: if "date" in start:
startDate = datetime.strptime(start['date'], '%Y-%m-%d').date() startDate = datetime.strptime(start["date"], "%Y-%m-%d").date()
elif 'dateTime' in start: elif "dateTime" in start:
startDate = datetime.strptime(start['dateTime'][:10], '%Y-%m-%d').date() startDate = datetime.strptime(start["dateTime"][:10], "%Y-%m-%d").date()
else: else:
print('Error') print("Error")
print(start) print(start)
return None return None
if startDate < datetime.today().date(): if startDate < datetime.today().date():
return datetime.today().date() return datetime.today().date()
else: return startDate else:
return startDate
itemStart = 80 itemStart = 80
try: try:
for key, group in groupby(events, get_start_date): for key, group in groupby(events, get_start_date):
if key == datetime.today().date(): if key == datetime.today().date():
dateStr = 'Today' dateStr = "Today"
elif key == (datetime.today() + timedelta(days=1)).date(): elif key == (datetime.today() + timedelta(days=1)).date():
dateStr = 'Tomorrow' dateStr = "Tomorrow"
else: else:
dateStr = key.strftime('%d %b') dateStr = key.strftime("%d %b")
draw.text((215, itemStart), dateStr, black, fontLarge) draw.text((215, itemStart), dateStr, black, fontLargeBold)
w, h = getsize(fontLarge, 'Today') w, h = getsize(fontLarge, "Today")
itemStart += h + (ep) itemStart += h + (ep)
for thing in list(group): for thing in list(group):
reflowedItem = reflow_quote(thing['summary'], 170, fontSmall) reflowedItem = reflow_quote(thing["summary"], 170, fontSmall)
w, h = getsize(fontLarge, 'Today') w, h = getsize(fontLarge, "Today")
h *= (reflowedItem.count('\n') + 1) h *= reflowedItem.count("\n") + 1
# print(f'After {reflowedItem}, {itemStart + h}') # print(f'After {reflowedItem}, {itemStart + h}')
if itemStart + h > 270: raise Space if itemStart + h > 270:
raise Space
draw.text((230, itemStart), reflowedItem, black, fontSmall) draw.text((230, itemStart), reflowedItem, black, fontSmall)
itemStart += h + (ep) itemStart += h + (ep)
if itemStart > 250: raise Space if itemStart > 250:
raise Space
except Space: except Space:
pass pass
return image return image
if __name__ == "__main__": if __name__ == "__main__":
load_dotenv() load_dotenv()
img = draw_image() img = draw_image()
img.save('built.bmp') img.save("built.bmp")

5
dev_reqs.txt Normal file
View File

@@ -0,0 +1,5 @@
pillow
imgkit
requests
python-dotenv
python-dateutil

View File

@@ -3,20 +3,46 @@ import datetime
from dotenv import load_dotenv from dotenv import load_dotenv
import os import os
def get_calendar_events(): def get_calendar_events():
token = os.getenv('HAS_TOKEN') token = os.getenv("HAS_TOKEN")
if not token: if not token:
raise Exception('Missing HAS token') raise Exception("Missing HAS token")
headers = {"Authorization": f"Bearer {token}"} headers = {"Authorization": f"Bearer {token}"}
payload = { payload = {
'start': datetime.datetime.now().strftime('%Y-%m-%d'), "start": datetime.datetime.now().strftime("%Y-%m-%d"),
'end': (datetime.datetime.now() + datetime.timedelta(days=14)).strftime('%Y-%m-%d')} "end": (datetime.datetime.now() + datetime.timedelta(days=14)).strftime(
response = requests.get('https://has.nozzy.online/api/calendars/calendar.romosborne_gmail_com', "%Y-%m-%d"
),
}
response = requests.get(
"https://has.nozzy.online/api/calendars/calendar.romosborne_gmail_com",
headers=headers, headers=headers,
params=payload) params=payload,
)
return response.json() return response.json()
def get_todo_items():
token = os.getenv("HAS_TOKEN")
if not token:
raise Exception("Missing HAS token")
headers = {"Authorization": f"Bearer {token}"}
payload = {"entity_id": "todo.todo_2"}
params = {"return_response": "null"}
response = requests.post(
"https://has.nozzy.online/api/services/todo/get_items",
headers=headers,
params=params,
json=payload,
)
data = response.json()
return data["service_response"]["todo.todo_2"]["items"]
if __name__ == "__main__": if __name__ == "__main__":
load_dotenv() load_dotenv()
events = get_calendar_events() events = get_todo_items()
for item in events:
print(item["summary"])