2023-09-29 10:08:43 +00:00
|
|
|
#!/usr/bin/python
|
2023-09-30 11:52:06 +00:00
|
|
|
import os
|
2023-09-29 10:08:43 +00:00
|
|
|
import sys
|
|
|
|
import time
|
|
|
|
import traceback
|
2023-12-18 07:00:07 +00:00
|
|
|
from calendar import timegm
|
2023-09-29 10:08:43 +00:00
|
|
|
from datetime import datetime, timedelta
|
|
|
|
|
|
|
|
import pytz
|
|
|
|
from requests import get
|
|
|
|
|
|
|
|
from hosted import config, node
|
|
|
|
|
|
|
|
config.restart_on_update()
|
|
|
|
|
2023-09-30 11:52:06 +00:00
|
|
|
SEND_PREFIX = os.environ["NODE"].replace("root/", "root/plugin/")
|
|
|
|
|
2023-09-29 10:08:43 +00:00
|
|
|
|
|
|
|
def log(msg):
|
|
|
|
sys.stderr.write("[pretalx] {}\n".format(msg))
|
|
|
|
|
|
|
|
|
2024-01-16 08:04:45 +00:00
|
|
|
def idle(seconds, event_start, event_end, event_tz):
|
2023-09-29 10:08:43 +00:00
|
|
|
end = time.time() + seconds
|
|
|
|
log("sleeping for {} seconds".format(seconds))
|
|
|
|
while time.time() < end:
|
2023-12-18 10:30:50 +00:00
|
|
|
send_data = {
|
|
|
|
"clock": "??",
|
|
|
|
"day": "??",
|
|
|
|
"time": int(time.time()),
|
|
|
|
}
|
2023-09-29 10:08:43 +00:00
|
|
|
if event_start is not None:
|
2023-09-30 07:37:26 +00:00
|
|
|
event_now = datetime.now(event_tz)
|
2023-09-29 10:08:43 +00:00
|
|
|
utc_now = datetime.now(pytz.utc)
|
|
|
|
|
2023-09-30 13:06:39 +00:00
|
|
|
day_zero = event_tz.localize(
|
|
|
|
event_start.replace(hour=0, minute=0, second=0)
|
2023-09-29 10:08:43 +00:00
|
|
|
) - timedelta(days=1)
|
|
|
|
|
|
|
|
day_info = event_now - day_zero
|
|
|
|
|
|
|
|
log("Day0: {}".format(day_zero.isoformat()))
|
|
|
|
log("NOW: {}".format(event_now.isoformat()))
|
|
|
|
|
2023-12-18 10:30:50 +00:00
|
|
|
send_data["clock"] = event_now.strftime(config["clock_format"])
|
2023-09-30 07:39:21 +00:00
|
|
|
send_data["day"] = day_info.days
|
2023-09-29 10:08:43 +00:00
|
|
|
|
2024-01-16 08:04:45 +00:00
|
|
|
# "single day" is only used in standalone mode to hide the
|
|
|
|
# the day information
|
|
|
|
if event_end is not None:
|
|
|
|
if event_start == event_end:
|
|
|
|
send_data["single_day"] = 1
|
|
|
|
else:
|
|
|
|
send_data["single_day"] = 0
|
|
|
|
|
2023-09-30 07:39:21 +00:00
|
|
|
for k, v in send_data.items():
|
2023-09-30 11:52:06 +00:00
|
|
|
node.send_raw("{}/{}:{}".format(SEND_PREFIX, k, v))
|
2023-09-29 10:08:43 +00:00
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
event_info = None
|
|
|
|
event_start = None
|
2024-01-16 08:04:45 +00:00
|
|
|
event_end = None
|
2023-09-29 10:08:43 +00:00
|
|
|
schedule = None
|
2023-09-30 07:37:26 +00:00
|
|
|
event_tz = pytz.utc
|
2023-09-29 10:08:43 +00:00
|
|
|
|
|
|
|
while True:
|
2023-12-18 05:52:01 +00:00
|
|
|
schedule_url = config["schedule_url"]
|
|
|
|
if "example.com" in schedule_url:
|
|
|
|
log("default schedule url, waiting for config update")
|
2023-09-29 10:08:43 +00:00
|
|
|
# sleep forever, service will get restarted if the config
|
|
|
|
# changes.
|
|
|
|
time.sleep(99999999)
|
2023-12-18 05:52:01 +00:00
|
|
|
log("event url: {}".format(schedule_url))
|
2023-12-18 06:58:01 +00:00
|
|
|
log("using json flavour: {}".format(config["json_flavour"]))
|
2023-12-18 05:52:01 +00:00
|
|
|
|
2023-12-18 06:58:01 +00:00
|
|
|
if config["json_flavour"] == "pretalx-broadcast-tools":
|
2023-12-18 05:52:01 +00:00
|
|
|
if not schedule_url.endswith("/"):
|
|
|
|
schedule_url = schedule_url + "/"
|
|
|
|
try:
|
|
|
|
r = get(
|
|
|
|
schedule_url + "p/broadcast-tools/event.json",
|
|
|
|
)
|
|
|
|
r.raise_for_status()
|
|
|
|
except Exception as e:
|
|
|
|
log("updating event info failed: {}".format(repr(e)))
|
|
|
|
# Only print the error message. If we have fetched the event
|
|
|
|
# info json blob atleast once, we have all the information
|
|
|
|
# we need.
|
|
|
|
else:
|
|
|
|
event_info = r.json()
|
|
|
|
|
|
|
|
if event_info is not None:
|
|
|
|
event_start = datetime.strptime(event_info["start"], "%Y-%m-%d")
|
2024-01-16 08:04:45 +00:00
|
|
|
event_end = datetime.strptime(event_info["end"], "%Y-%m-%d")
|
2023-12-18 05:52:01 +00:00
|
|
|
event_tz = pytz.timezone(event_info["timezone"])
|
|
|
|
|
|
|
|
try:
|
|
|
|
r = get(
|
|
|
|
schedule_url + "p/broadcast-tools/schedule.json",
|
2023-09-30 07:39:21 +00:00
|
|
|
)
|
2023-12-18 05:52:01 +00:00
|
|
|
r.raise_for_status()
|
|
|
|
except Exception as e:
|
|
|
|
log("updating schedule failed: {}".format(repr(e)))
|
|
|
|
# Only print the error message. If we have fetched the schedule
|
|
|
|
# info json blob atleast once, we have all the information
|
|
|
|
# we need.
|
|
|
|
else:
|
|
|
|
schedule = r.json()
|
2024-01-16 07:47:47 +00:00
|
|
|
tracks = {}
|
2023-12-18 05:52:01 +00:00
|
|
|
for talk in schedule["talks"]:
|
|
|
|
talk["start_str"] = (
|
|
|
|
datetime.fromtimestamp(talk["start_ts"])
|
|
|
|
.replace(tzinfo=pytz.utc)
|
|
|
|
.astimezone(event_tz)
|
|
|
|
.strftime("%H:%M")
|
|
|
|
)
|
2024-01-16 07:47:47 +00:00
|
|
|
if talk["track"]:
|
|
|
|
if talk["track"]["name"] not in tracks:
|
|
|
|
tracks[talk["track"]["name"]] = talk["track"]["color"]
|
|
|
|
schedule["tracks"] = []
|
|
|
|
for name, color in sorted(tracks.items()):
|
|
|
|
schedule["tracks"].append(
|
|
|
|
{
|
|
|
|
"name": name,
|
|
|
|
"color": color,
|
|
|
|
}
|
|
|
|
)
|
2023-12-18 05:52:01 +00:00
|
|
|
node.write_json("schedule.json", schedule)
|
|
|
|
log("updated schedule json")
|
2023-12-18 06:58:01 +00:00
|
|
|
elif config["json_flavour"] == "voc-schema":
|
2023-12-18 05:52:01 +00:00
|
|
|
try:
|
|
|
|
r = get(schedule_url)
|
|
|
|
r.raise_for_status()
|
|
|
|
except Exception as e:
|
|
|
|
log("getting schedule.json failed: {}".format(repr(e)))
|
|
|
|
else:
|
2023-12-18 07:00:07 +00:00
|
|
|
raw_schedule = r.json()["schedule"]
|
2023-12-23 15:19:33 +00:00
|
|
|
schedule = {
|
|
|
|
"tracks": raw_schedule["conference"]["tracks"],
|
|
|
|
"talks": [],
|
|
|
|
}
|
2023-12-18 05:52:01 +00:00
|
|
|
|
2023-12-18 06:58:01 +00:00
|
|
|
event_start = datetime.strptime(
|
|
|
|
raw_schedule["conference"]["start"][:10], "%Y-%m-%d"
|
|
|
|
)
|
2024-01-16 08:04:45 +00:00
|
|
|
event_end = datetime.strptime(
|
|
|
|
raw_schedule["conference"]["end"][:10], "%Y-%m-%d"
|
|
|
|
)
|
2023-12-18 05:52:01 +00:00
|
|
|
event_tz = pytz.timezone(raw_schedule["conference"]["time_zone_name"])
|
|
|
|
|
2023-12-18 07:00:07 +00:00
|
|
|
for day in raw_schedule["conference"]["days"]:
|
2023-12-18 05:52:01 +00:00
|
|
|
for room in day["rooms"].values():
|
|
|
|
for talk in room:
|
2024-01-16 07:50:09 +00:00
|
|
|
start = event_tz.localize(
|
|
|
|
datetime.strptime(
|
|
|
|
talk["date"][:19], "%Y-%m-%dT%H:%M:%S"
|
|
|
|
)
|
|
|
|
)
|
2023-12-18 05:52:01 +00:00
|
|
|
d_h, d_m = talk["duration"].split(":")
|
|
|
|
end = start + timedelta(hours=int(d_h), minutes=int(d_m))
|
|
|
|
|
2024-01-16 07:50:09 +00:00
|
|
|
talk["start_ts"] = int(
|
|
|
|
timegm(start.timetuple())
|
|
|
|
- start.utcoffset().total_seconds()
|
|
|
|
)
|
2023-12-18 05:52:01 +00:00
|
|
|
talk["start_str"] = talk["start"]
|
2024-01-16 07:50:09 +00:00
|
|
|
talk["end_ts"] = int(
|
|
|
|
timegm(end.timetuple())
|
|
|
|
- end.utcoffset().total_seconds()
|
|
|
|
)
|
2023-12-18 05:52:01 +00:00
|
|
|
talk["locale"] = talk["language"]
|
|
|
|
|
|
|
|
track = None
|
|
|
|
if talk["track"]:
|
|
|
|
for t in raw_schedule["conference"]["tracks"]:
|
|
|
|
if t["name"] == talk["track"]:
|
|
|
|
track = {
|
|
|
|
"color": t["color"],
|
|
|
|
"name": t["name"],
|
|
|
|
}
|
|
|
|
break
|
|
|
|
talk["track"] = track
|
|
|
|
|
|
|
|
persons = []
|
|
|
|
for p in talk["persons"]:
|
2024-02-25 08:21:19 +00:00
|
|
|
name = p.get("public_name", p.get("name"))
|
|
|
|
if name:
|
|
|
|
persons.append(name)
|
2023-12-18 05:52:01 +00:00
|
|
|
talk["persons"] = persons
|
|
|
|
|
|
|
|
schedule["talks"].append(talk)
|
|
|
|
node.write_json("schedule.json", schedule)
|
|
|
|
log("updated schedule json")
|
2023-12-18 06:58:01 +00:00
|
|
|
else:
|
|
|
|
log("unknown json flavour, something is very wrong")
|
2023-09-29 10:08:43 +00:00
|
|
|
|
2024-01-16 08:04:45 +00:00
|
|
|
idle(30, event_start, event_end, event_tz)
|
2023-09-29 10:08:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
try:
|
|
|
|
main()
|
|
|
|
except:
|
|
|
|
traceback.print_exc()
|
|
|
|
time.sleep(30)
|