fixes for the service layer. Updated readme.

This commit is contained in:
2026-06-13 21:29:25 -07:00
parent bfad71e96a
commit e9ff109f0a
3 changed files with 71 additions and 16 deletions
+40
View File
@@ -1,5 +1,6 @@
"""HTTP server that serves the Guardian Daily Newscast MP3 index page and audio files."""
import glob
import os
import json
import threading
@@ -65,6 +66,41 @@ class NewscastHandler(SimpleHTTPRequestHandler):
"""Suppress per-request logs to avoid noisy output."""
pass
def do_POST(self):
if self.path == "/clear":
self.clear_audio()
else:
self.send_error(405, "Method Not Allowed")
def clear_audio(self):
"""Remove all MP3 files from the audio directory."""
if ".." in self.path:
self.send_error(403, "Forbidden")
return
audio_dir = os.path.join(self.data_dir, "audio")
if not os.path.isdir(audio_dir):
self._json_response({"status": "ok", "cleared": 0})
return
mp3_paths = glob.glob(os.path.join(audio_dir, "*.mp3"))
count = 0
for path in mp3_paths:
try:
os.remove(path)
count += 1
except OSError:
logger.exception(f"Failed to remove {path}")
logger.info(f"Cleared {count} audio files.")
self._json_response({"status": "ok", "cleared": count})
def _json_response(self, data):
"""Send a JSON response."""
body = json.dumps(data).encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def _generate_index(mp3_files, scripts_map):
"""Generate the HTML index page for the MP3 newscast."""
@@ -107,9 +143,12 @@ def _generate_index(mp3_files, scripts_map):
.empty {{ text-align: center; color: #8b949e; padding: 3rem 0; }}
.refresh-btn {{ background: #21262d; color: #c9d1d9; border: 1px solid #30363d; padding: 0.5rem 1rem; border-radius: 6px; cursor: pointer; font-size: 0.85rem; margin-bottom: 1.5rem; }}
.refresh-btn:hover {{ background: #30363d; }}
.clear-btn {{ background: #490202; color: #f85149; border: 1px solid #f85149; padding: 0.5rem 1rem; border-radius: 6px; cursor: pointer; font-size: 0.85rem; margin-bottom: 1.5rem; }}
.clear-btn:hover {{ background: #da3633; color: #fff; }}
</style>
<script>
function refresh() {{ location.reload(); }}
function clearAudio() {{ fetch('/clear', {{ method: 'POST' }}).then(() => location.reload()); }}
setInterval(refresh, 300000);
</script>
</head>
@@ -118,6 +157,7 @@ def _generate_index(mp3_files, scripts_map):
<h1>Guardian Daily Newscast</h1>
<p class="subtitle">Daily US news — spoken by AI</p>
<button class="refresh-btn" onclick="refresh()">Refresh</button>
<button class="clear-btn" onclick="clearAudio()">Clear Audio</button>
{audio_entries}
</div>
</body>