Compare commits
4 commits
30b300986c
...
42062c2eb6
Author | SHA1 | Date | |
---|---|---|---|
42062c2eb6 | |||
ec86c1c307 | |||
c99f6b507e | |||
9589d0a9f0 |
2 changed files with 176 additions and 4 deletions
168
daily-todo.py
Normal file
168
daily-todo.py
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from datetime import date, datetime, timedelta
|
||||||
|
from random import randint
|
||||||
|
|
||||||
|
from caldav import DAVClient
|
||||||
|
from dotenv import find_dotenv, load_dotenv
|
||||||
|
|
||||||
|
from printer import p
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
format="{asctime} {levelname:8} {name}: {message}",
|
||||||
|
datefmt="%Y-%m-%d %H:%M:%S",
|
||||||
|
style="{",
|
||||||
|
stream=sys.stdout,
|
||||||
|
force=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
log = logging.getLogger("todo-receipt")
|
||||||
|
log.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
if load_dotenv(find_dotenv(usecwd=True)):
|
||||||
|
log.debug("Loaded .env")
|
||||||
|
else:
|
||||||
|
log.debug("Didn't find .env")
|
||||||
|
|
||||||
|
CALDAV_URL = os.getenv("CALDAV_URL")
|
||||||
|
CALDAV_USERNAME = os.getenv("CALDAV_USERNAME")
|
||||||
|
CALDAV_PASSWORD = os.getenv("CALDAV_PASSWORD")
|
||||||
|
|
||||||
|
day = timedelta(days=1)
|
||||||
|
week = timedelta(days=7)
|
||||||
|
today = date.today()
|
||||||
|
yesterday = today - day
|
||||||
|
tomorrow = today + day
|
||||||
|
next_week = today + week
|
||||||
|
|
||||||
|
|
||||||
|
def coerce_date(datetime):
|
||||||
|
try:
|
||||||
|
return datetime.date()
|
||||||
|
except:
|
||||||
|
return datetime
|
||||||
|
|
||||||
|
|
||||||
|
def shuffle_with_priority(tasks):
|
||||||
|
return sorted(
|
||||||
|
tasks,
|
||||||
|
key=lambda task: (
|
||||||
|
task.icalendar_component.get("priority", 5),
|
||||||
|
randint(0, 10),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
with DAVClient(
|
||||||
|
url=CALDAV_URL, username=CALDAV_USERNAME, password=CALDAV_PASSWORD
|
||||||
|
) as client:
|
||||||
|
log.debug("Loading calendars")
|
||||||
|
principal = client.principal()
|
||||||
|
calendars = principal.calendars()
|
||||||
|
|
||||||
|
events = []
|
||||||
|
todos = []
|
||||||
|
|
||||||
|
for c in calendars:
|
||||||
|
log.debug(f"Fetching from {c.name}")
|
||||||
|
if c.name not in ["Schedule"]:
|
||||||
|
log.debug("Fetching events and todos")
|
||||||
|
events.extend(c.events())
|
||||||
|
todos.extend(c.todos())
|
||||||
|
else:
|
||||||
|
log.debug("Finding cancelled classes")
|
||||||
|
for event in c.events():
|
||||||
|
if event.icalendar_component.get("status") == "CANCELED":
|
||||||
|
log.debug(
|
||||||
|
f"Found cancelled class {event.icalendar_component.get('summary')}"
|
||||||
|
)
|
||||||
|
events.append(event)
|
||||||
|
|
||||||
|
must_do = []
|
||||||
|
should_do = []
|
||||||
|
want_to_do = []
|
||||||
|
|
||||||
|
log.debug("Processing todos")
|
||||||
|
for task in todos:
|
||||||
|
due = task.get_due()
|
||||||
|
if due is None:
|
||||||
|
want_to_do.append(task)
|
||||||
|
continue
|
||||||
|
|
||||||
|
task.expand_rrule(yesterday, next_week)
|
||||||
|
due = coerce_date(due)
|
||||||
|
|
||||||
|
start = coerce_date(task.icalendar_component.get("dtstart").dt or yesterday)
|
||||||
|
|
||||||
|
if today < start:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if due < tomorrow:
|
||||||
|
must_do.append(task)
|
||||||
|
elif due < next_week:
|
||||||
|
should_do.append(task)
|
||||||
|
else:
|
||||||
|
want_to_do.append(task)
|
||||||
|
|
||||||
|
scheduled = []
|
||||||
|
|
||||||
|
log.debug("Processing events")
|
||||||
|
for event in events:
|
||||||
|
event.expand_rrule(yesterday, next_week)
|
||||||
|
start_day = coerce_date(event.icalendar_component.get("dtstart").dt)
|
||||||
|
end_day = coerce_date(event.icalendar_component.get("dtend").dt)
|
||||||
|
|
||||||
|
if end_day < today or today < start_day:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
scheduled.append(event)
|
||||||
|
|
||||||
|
should_do = shuffle_with_priority(should_do)
|
||||||
|
want_to_do = shuffle_with_priority(want_to_do)
|
||||||
|
|
||||||
|
while len(must_do) < 2:
|
||||||
|
if should_do:
|
||||||
|
must_do.append(should_do.pop(0))
|
||||||
|
elif want_to_do:
|
||||||
|
must_do.append(want_to_do.pop(0))
|
||||||
|
else:
|
||||||
|
break # No remaining tasks
|
||||||
|
|
||||||
|
while len(should_do) < 3:
|
||||||
|
if want_to_do:
|
||||||
|
should_do.append(want_to_do.pop(0))
|
||||||
|
else:
|
||||||
|
break # No remaining tasks
|
||||||
|
|
||||||
|
categories = {
|
||||||
|
"Must do": must_do,
|
||||||
|
"Should do": should_do[:3],
|
||||||
|
"Want to do": want_to_do[:3],
|
||||||
|
}
|
||||||
|
|
||||||
|
with p:
|
||||||
|
log.debug("Printing output")
|
||||||
|
p.title(" TODO List ", size=4)
|
||||||
|
p.subtitle(datetime.today().strftime("%Y-%m-%d"))
|
||||||
|
p.ln()
|
||||||
|
|
||||||
|
if scheduled:
|
||||||
|
p.textln("Scheduled:")
|
||||||
|
for event in scheduled:
|
||||||
|
summary = event.icalendar_component["summary"]
|
||||||
|
if event.icalendar_component.get("status") == "CANCELED":
|
||||||
|
summary += " (CANCELED)"
|
||||||
|
start = event.icalendar_component.get("dtstart").dt
|
||||||
|
p.textln(f"[ ] {summary} @ {start.strftime('%H:%M')}")
|
||||||
|
else:
|
||||||
|
p.textln("Scheduled: (None)")
|
||||||
|
|
||||||
|
for k, v in categories.items():
|
||||||
|
p.ln()
|
||||||
|
if v:
|
||||||
|
p.textln(f"{k}:")
|
||||||
|
for task in v:
|
||||||
|
p.textln(f"[ ] {task.icalendar_component['summary']}")
|
||||||
|
else:
|
||||||
|
p.textln(f"{k}: (None)")
|
|
@ -23,9 +23,13 @@ in
|
||||||
# alias print="lp -d EPSON-TM-m30 -o lpi=10 -o cpi=15"
|
# alias print="lp -d EPSON-TM-m30 -o lpi=10 -o cpi=15"
|
||||||
devshell.mkShell {
|
devshell.mkShell {
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
(python3.withPackages (p: with p; [
|
(python3.withPackages (
|
||||||
|
p: with p; [
|
||||||
python-escpos
|
python-escpos
|
||||||
pycups
|
pycups
|
||||||
]))
|
caldav
|
||||||
|
python-dotenv
|
||||||
|
]
|
||||||
|
))
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue