80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
#!/usr/bin/python3
|
|
|
|
"""calendar reminder
|
|
|
|
this logs into a caldav server and get a digest of all of the
|
|
events scheduled for next days. Good candidate to run from cron
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
from dotenv import load_dotenv
|
|
|
|
from datetime import timedelta, date
|
|
from os import environ
|
|
from urllib.parse import quote_plus
|
|
import caldav
|
|
|
|
load_dotenv()
|
|
|
|
# read parameters from dot env
|
|
USERNAME = os.getenv('CALDAV_USERNAME')
|
|
PASSWORD = os.getenv('CALDAV_PASSWORD')
|
|
BASE_URL = os.getenv('CALDAV_URL')
|
|
NEXT_DAYS = int(os.getenv('NEXT_DAYS'))
|
|
|
|
|
|
def fill_event(component, calendar) -> dict[str, str]:
|
|
# quite some data is tossed away here - like, the recurring rule.
|
|
cur = {}
|
|
cur["calendar"] = f"{calendar}"
|
|
cur["summary"] = component.get("summary")
|
|
cur["description"] = component.get("description")
|
|
# month/day/year time? Never ever do that!
|
|
# It's one of the most confusing date formats ever!
|
|
# Use year-month-day time instead ... https://xkcd.com/1179/
|
|
cur["start"] = component.start.strftime("%m/%d/%Y %H:%M")
|
|
endDate = component.end
|
|
if endDate:
|
|
cur["end"] = endDate.strftime("%m/%d/%Y %H:%M")
|
|
return cur
|
|
|
|
|
|
def fill_todo(component, calendar) -> dict[str, str]:
|
|
cur = {}
|
|
cur["calendar"] = f"{calendar}"
|
|
cur["summary"] = component.get("summary")
|
|
cur["description"] = component.get("description")
|
|
return cur
|
|
|
|
|
|
def display_event(event: dict[str, str]):
|
|
print(event["start"] + " " + event["calendar"] + "/" + event["summary"])
|
|
|
|
|
|
def display_todo(todo: dict[str, str]):
|
|
print("Todo : " + todo["summary"])
|
|
|
|
|
|
url = 'https://' + quote_plus(USERNAME) + ":" + quote_plus(PASSWORD) \
|
|
+ '@' + BASE_URL + quote_plus(USERNAME) + '/'
|
|
start = date.today()
|
|
end = start + timedelta(days=NEXT_DAYS)
|
|
client = caldav.DAVClient(url)
|
|
calendars = client.principal().calendars()
|
|
|
|
if not calendars:
|
|
print("No calendars defined for " + USERNAME)
|
|
sys.exit(0)
|
|
|
|
for cal in calendars:
|
|
events = cal.search(event=True, start=start, end=end, expand=True) \
|
|
+ cal.search(todo=True)
|
|
for event in events:
|
|
for component in event.icalendar_instance.walk():
|
|
if component.name == "VEVENT":
|
|
display_event(fill_event(component, cal))
|
|
elif component.name == "VTODO":
|
|
display_todo(fill_todo(component, cal))
|
|
|
|
print(".")
|