Skip to content

Commit d94e2f3

Browse files
committed
schedule/feeds: make json feed schema compatible
1 parent 463b16f commit d94e2f3

File tree

1 file changed

+134
-2
lines changed

1 file changed

+134
-2
lines changed

apps/schedule/feeds.py

+134-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
from flask import request, abort, current_app as app, Response
44
from flask_cors import cross_origin
55
from flask_login import current_user
6+
from math import ceil
67

7-
from models import event_year
8+
from main import external_url
9+
from models import event_year, event_start, event_end
810
from models.user import User
911
from models.cfp import Proposal
1012

@@ -17,7 +19,7 @@
1719
_convert_time_to_str,
1820
_get_upcoming,
1921
)
20-
from . import schedule
22+
from . import event_tz, schedule
2123

2224

2325
def _format_event_description(event):
@@ -46,6 +48,136 @@ def schedule_json(year):
4648
return Response(json.dumps(schedule), mimetype="application/json")
4749

4850

51+
@schedule.route("/schedule/schedule-<int:year>.json") # TODO validate url with upstream
52+
@cross_origin(methods=["GET"])
53+
def schedule_json_schema(year):
54+
if year != event_year():
55+
return feed_historic(year, "json")
56+
57+
if not feature_enabled('SCHEDULE'):
58+
abort(404)
59+
60+
def duration_hhmm(duration_minutes):
61+
if not duration_minutes or duration_minutes < 1:
62+
return "00:00"
63+
return "{}:{}".format(
64+
int(duration_minutes/60),
65+
str(duration_minutes%60).zfill(2),
66+
)
67+
68+
schedule = (
69+
Proposal.query.filter(
70+
Proposal.is_accepted,
71+
Proposal.scheduled_time.isnot(None),
72+
Proposal.scheduled_venue_id.isnot(None),
73+
Proposal.scheduled_duration.isnot(None),
74+
)
75+
.order_by(Proposal.scheduled_time)
76+
.all()
77+
)
78+
79+
duration_days = ceil((event_end() - event_end()).total_seconds / 86400),
80+
81+
rooms = [
82+
proposal.scheduled_venue.name
83+
for proposal in schedule
84+
]
85+
86+
schedule_json = {
87+
"version": "1.0-public",
88+
"conference": {
89+
"acronym": "emf{}".format(event_year()),
90+
"days": [],
91+
"daysCount": duration_days,
92+
"end": event_end().strftime("%Y-%m-%d"),
93+
"rooms": [
94+
{
95+
"name": room,
96+
}
97+
for room in rooms
98+
],
99+
"start": event_start().strftime("%Y-%m-%d"),
100+
"time_zone_name": event_tz,
101+
"timeslot_duration": "00:10",
102+
"title": "Electromagnetic Field {}".format(event_year()),
103+
"url": external_url("main"),
104+
},
105+
}
106+
107+
for day in range(0, duration_days):
108+
day_dt = event_start() + timedelta(days=day)
109+
day_schedule = {
110+
"date": day_dt.strftime("%Y-%m-%d"),
111+
"day_end": (day_dt.replace(hour=3, minute=59, second=59) + timedelta(days=1)).isoformat(),
112+
"day_start": day_dt.replace(hour=4, minute=0, second=0).isoformat(),
113+
"index": day,
114+
"rooms": {},
115+
}
116+
for room in rooms:
117+
day_schedule["rooms"][room] = []
118+
for proposal in schedule:
119+
if proposal.scheduled_venue.name != room:
120+
# TODO find a better way to do that
121+
continue
122+
links = {
123+
proposal.c3voc_url,
124+
proposal.youtube_url,
125+
proposal.thumbnail_url,
126+
proposal.map_link,
127+
}
128+
links.discard(None)
129+
links.discard("")
130+
day_schedule["rooms"][room].append({
131+
"abstract": None, # The proposal model does not implement abstracts
132+
"attachments": [],
133+
"date": event_tz.localize(proposal.start_date).isoformat(),
134+
"description": proposal.description,
135+
"do_not_record": False if proposal.may_record else True,
136+
"duration": duration_hhmm(proposal.duration_minutes),
137+
"guid": None,
138+
"id": proposal.id,
139+
# This assumes there will never be a non-english talk,
140+
# which is probably fine for a conference in the UK.
141+
"language": "en",
142+
"links": sorted(links),
143+
"persons": [
144+
{
145+
"name": name.strip(),
146+
"public_name": name.strip(),
147+
}
148+
for person in (proposal.published_names or proposal.user.name).split(",")
149+
],
150+
"recording_license": "CC BY-SA 3.0",
151+
"room": room,
152+
"slug": "emf{}-{}-{}".format(
153+
event_year(),
154+
proposal.id,
155+
proposal.slug,
156+
),
157+
"start": event_tz.localize(proposal.start_date).strftime("%H:%M"),
158+
"subtitle": None,
159+
"title": proposal.display_title,
160+
"track": None, # TODO does emf have tracks?
161+
"type": proposal.type,
162+
"url": external_url(
163+
".item",
164+
year=event_year(),
165+
proposal_id=proposal.id,
166+
slug=proposal.slug,
167+
),
168+
})
169+
schedule_json["conference"]["days"].append(day_schedule)
170+
171+
return Response(json.dumps({
172+
"schedule": schedule_json,
173+
"$schema": "https://c3voc.de/schedule/schema.json",
174+
"generator": {
175+
"name": "emfcamp-website",
176+
"url": "https://github.com/emfcamp/Website",
177+
},
178+
}), mimetype="application/json")
179+
180+
49181
@schedule.route("/schedule/<int:year>.frab")
50182
def schedule_frab(year):
51183
if year != event_year():

0 commit comments

Comments
 (0)