[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:
parent
05ccf45dca
commit
f3060c0806
66
ptgbot/ics.py
Normal file
66
ptgbot/ics.py
Normal 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()
|
@ -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)
|
||||
|
||||
|
@ -3,3 +3,4 @@ irc==15.1.1
|
||||
python-daemon >= 1.6
|
||||
ib3
|
||||
requests
|
||||
icalendar >= 5.0.0
|
||||
|
Loading…
Reference in New Issue
Block a user