Todo items from HAS
This commit is contained in:
14
README.md
Normal file
14
README.md
Normal 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
|
||||||
|
```
|
||||||
90
building.py
90
building.py
@@ -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
5
dev_reqs.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
pillow
|
||||||
|
imgkit
|
||||||
|
requests
|
||||||
|
python-dotenv
|
||||||
|
python-dateutil
|
||||||
40
hasApi.py
40
hasApi.py
@@ -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"])
|
||||||
|
|||||||
Reference in New Issue
Block a user