[iCal] Add an iCal file route.

Add a handler that converts the existing slot data into an ICS file.
This .ics file can be global ".../ptg.ics" or per track ".../ironic.ics"

Right now each block deafults to 60 minutes if there isn't a 'duration'
field in the slot entry.

Change-Id: I7a67ba777c004e57206976aca377fe3f41956db0
This commit is contained in:
Tony Breeds 2023-06-07 09:29:33 -05:00
parent 05ccf45dca
commit f3060c0806
3 changed files with 78 additions and 0 deletions

66
ptgbot/ics.py Normal file
View File

@ -0,0 +1,66 @@
import datetime
import icalendar
def json2ical(db, include_teams="ALL"):
teams = slots = {}
# FIXME: The unused label and the _slots here are irritating.
for label, _slots in db["slots"].items():
for slot in _slots:
slots[slot["name"]] = slot
for location, schedule in db["schedule"].items():
for slot in schedule:
team = schedule[slot]
# FIXME: This is possibly wrong as teams can globally override the
# VC url and ignore the setting in the room/slot/table
if slot == "url" or team == "":
continue
teams.setdefault(team, []).append((location, slot))
if include_teams in ["ALL", "ptg"]:
include_teams = list(teams.keys())
if isinstance(include_teams, str):
include_teams = [include_teams]
c = icalendar.Calendar()
c.add("prodid", "-//Opendev PTGBot//ptg.opendev.org//")
c.add("version", "2.0")
for team in include_teams:
for booking in teams.get(team, []):
location, slot = booking
url = db["schedule"].get(location, {}).get("url", "")
etherpad = db["etherpads"].get(team, "")
time = slots.get(slot, {}).get("realtime")
# TODO(tonyb): 60 mins is a default picked to make the existing
# DB work unchanged. We can leave this as is or pick another
# number. Longer term we could also potentially add a
# 'default_duration' to the DB as a per-event not hard-coded
# value to save adding a 'duration' to each slot.
duration = slots.get(slot, {}).get("duration", 60)
dtstart = datetime.datetime.fromisoformat(time)
name = summary = "[PTG] " + team
desc = "Etherpad: " + etherpad + "\n"
uid = (dtstart.strftime("%Y%m%d%H%M") + "/" + location +
"@ptg.opendev.org")
e = icalendar.Event()
e.add("name", name)
e.add("summary", summary)
e.add("description", desc)
e.add("dtstart", dtstart)
e.add("dtend", dtstart + datetime.timedelta(mins=duration))
e.add("priority", 0)
# FIXME: Why the change in format
# FIXME: Check for empty url? it shouldn't happen due to the
# way we build the the teams/bookings lists
e["location"] = icalendar.vText(url)
e["uid"] = uid
c.add_component(e)
return c.to_ical()

View File

@ -8,6 +8,9 @@ import os
import pkg_resources
import socketserver
import ptgbot.ics
CONFIG = {}
@ -19,6 +22,14 @@ class RequestHandler(http.server.SimpleHTTPRequestHandler):
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(fp.read())
elif self.path.endswith('.ics'):
team = os.path.basename(self.path)[:-4]
with open(CONFIG['db_filename'], 'rb') as fp:
ics = ptgbot.ics.json2ical(json.load(fp), team)
self.send_response(200)
self.send_header('Content-type', 'text/calendar')
self.end_headers()
self.wfile.write(ics)
else:
http.server.SimpleHTTPRequestHandler.do_GET(self)

View File

@ -3,3 +3,4 @@ irc==15.1.1
python-daemon >= 1.6
ib3
requests
icalendar >= 5.0.0