calDAVtoCSV/main.py

80 lines
2.5 KiB
Python
Executable file

#!/usr/bin/env python
from datetime import datetime
from flask import Flask
from caldav import DAVClient, Calendar, Principal, Todo
import re
import configparser
def parseConfig() -> tuple[str, str, str, str]:
def passwordFromFile() -> str:
calDavPasswordFile = config.get("calDAV", "passwordFile")
with open(calDavPasswordFile, "r") as file:
return file.readline().strip()
config = configparser.ConfigParser()
# TODO: option to call the one in test instead or specify one
config.read("/etc/calDAVtoCSV/config.ini")
calDavAddress = config.get("calDAV", "address")
calDavUsername = config.get("calDAV", "username")
caldavpwd = config.get("calDAV", "password", fallback=None)
caldavpwd = caldavpwd if caldavpwd is not None else passwordFromFile()
calDavCalendarName = config.get("calDAV", "calendarName")
return calDavAddress, calDavUsername, caldavpwd, calDavCalendarName
def fetch_10_next_todos_as_csv() -> str:
def auth(add: str, user: str, pwd: str) -> Principal:
# TODO: on the final version, fetch it locally
client = DAVClient(url=add, username=user, password=pwd)
principal = client.principal()
return principal
def get_calendar(principal: Principal, name: str) -> Calendar:
calendar = principal.calendar(name=name)
return calendar
def filter_todos(todos: list[Todo]) -> list[Todo]:
today = datetime.today().date()
return [
todo
for todo in todos
if (
match := re.search(
r"\d{4}-\d{2}-\d{2}", todo.icalendar_component["due"]
)
)
and datetime.strptime(match.group(), "%Y-%m-%d").date() > today
]
def todos_to_csv(todos: list[Todo]) -> str:
result = "".join(
f"{todo.icalendar_component['uid']},{todo.icalendar_component['summary']}\n"
for todo in todos
)
return result
add, user, pwd, name = parseConfig()
principal = auth(add, user, pwd)
calendar = get_calendar(principal, name)
sorted_todos = calendar.todos(sort_keys=("due"))
cut_todos = sorted_todos[:10]
filtered_todos = filter_todos(cut_todos)
csv = todos_to_csv(filtered_todos)
return csv
app = Flask(__name__)
@app.route("/")
def send_events():
return fetch_10_next_todos_as_csv()
# not suitable for production apparently, just for testing
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)