Highlight export: CSV/JSON download, same-name highlights disambiguated per day, sorted chronologically

This commit is contained in:
2026-08-28 16:47:14 +01:00
parent 43561d5012
commit 8d194d5241
2 changed files with 46 additions and 0 deletions
+41
View File
@@ -102,6 +102,8 @@ class PlayerHandler(BaseHTTPRequestHandler):
return self.send_json(self.server.encode_status)
if request.path == "/api/highlights":
return self.send_json(self.server.highlights)
if request.path == "/api/highlights/export":
return self.export_highlights()
if request.path == "/api/system-highlights":
date = parse_qs(request.query).get("date", [""])[0]
return self.send_json([item for item in self.server.system_highlights if item["date"] == date])
@@ -149,6 +151,45 @@ class PlayerHandler(BaseHTTPRequestHandler):
return self.send_json(highlight)
self.send_error(404)
def export_highlights(self):
fmt = parse_qs(urlparse(self.path).query).get("format", ["csv"])[0].lower()
items = sorted(self.server.highlights, key=lambda h: (h["date"], h["start"], h["id"]))
seen = {}
rows = []
for item in items:
# same label may repeat across days; within one day duplicates get -2, -3...
key = (item["date"], item["label"])
seen[key] = seen.get(key, 0) + 1
name = item["label"] if seen[key] == 1 else f"{item['label']} ({seen[key]})"
def clock(sec):
return f"{sec // 3600:02d}:{sec % 3600 // 60:02d}:{sec % 60:02d}"
rows.append({
"date": f"{item['date'][:4]}-{item['date'][4:6]}-{item['date'][6:]}",
"name": name,
"start": clock(item["start"]),
"end": clock(item["end"]),
"duration_sec": item["end"] - item["start"],
"clip": f"{item['date']}/{item['start'] // 3600:02d}.{item['start'] % 3600 // 60:02d}.{item['start'] % 60:02d}",
})
if fmt == "json":
data = json.dumps(rows, indent=2).encode()
ctype = "application/json"
else:
import io
buf = io.StringIO()
writer = __import__("csv").writer(buf)
writer.writerow(["date", "name", "start", "end", "duration_sec", "clip"])
writer.writerows((r["date"], r["name"], r["start"], r["end"], r["duration_sec"], r["clip"]) for r in rows)
data = buf.getvalue().encode()
ctype = "text/csv"
stamp = datetime.now().strftime("%Y%m%d-%H%M%S")
self.send_response(200)
self.send_header("Content-Type", f"{ctype}; charset=utf-8")
self.send_header("Content-Disposition", f'attachment; filename="highlights-{stamp}.{fmt}"')
self.send_header("Content-Length", str(len(data)))
self.end_headers()
self.wfile.write(data)
def handle_upload(self):
try:
length = int(self.headers.get("Content-Length", "0"))