ical_offset/main.py

81 lines
2.5 KiB
Python

"""
Take existing calendar and update it slightly
"""
import logging
from datetime import date, datetime, time, timedelta
import requests
from flask import Flask, Response, make_response, request
from icalendar import Calendar, Event
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1) # type: ignore[assignment]
@app.route("/", methods=["get"])
def process() -> Response:
"""
Fetch ICS url and convert from Events to Todos
Returns:
Response: ical response
"""
# Fetch existing calendar
orig = requests.get(request.args["url"], timeout=30)
days = int(request.args.get("days", "0"))
hours = int(request.args.get("hours", "0"))
mins = int(request.args.get("mins", "0"))
if orig.status_code != 200:
logging.warning("%s returned a %d", orig.request.url, orig.status_code)
return make_response(orig.text, orig.status_code)
orig_cal = Calendar.from_ical(orig.text)
cal = Calendar()
cal.add("version", "2.0")
cal.add(
"prodid",
"-//Scott Wallace//event2task//EN",
)
for component in orig_cal.subcomponents:
if isinstance(component, Event):
entry = Event()
entry.add("description", component["description"])
entry.add("dtstamp", component["dtstamp"])
if days or hours or mins:
start = component.decoded("dtstart")
end = component.decoded("dtend")
if isinstance(start, date):
entry.add(
"dtstart",
datetime.combine(start, time(0))
+ timedelta(days=days, hours=hours, minutes=mins),
)
if isinstance(end, date):
entry.add(
"dtend",
datetime.combine(end, time(0))
+ timedelta(days=days, hours=hours, minutes=mins),
)
if not entry.get("dtstart"):
entry.add("dtstart", component["dtstart"])
if not entry.get("dtend"):
entry.add("dtend", component["dtend"])
entry.add("summary", component["summary"])
entry.add("uid", component["uid"])
cal.add_component(entry)
return Response(
cal.to_ical().decode().replace("\\r\\n", "\n").strip(),
headers={"content-type": "text/calendar; charset=UTF-8"},
)