Initial commit: self-hosted personal radio station
Flask + React web UI with audio player, podcast queue, feed management, episode browser, music library, schedule viewer, and log tail. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"""GET /api/status — stream status, now playing, queue depth, current schedule."""
|
||||
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
import yaml
|
||||
from flask import Blueprint, jsonify
|
||||
|
||||
from ..config import BASE_DIR, STATION_CONFIG
|
||||
from ..db import get_db
|
||||
|
||||
bp = Blueprint("status", __name__)
|
||||
|
||||
|
||||
def _get_current_schedule_block():
|
||||
"""Determine which schedule block is active right now."""
|
||||
try:
|
||||
with open(STATION_CONFIG) as f:
|
||||
config = yaml.safe_load(f)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
now = datetime.now()
|
||||
current_day = now.isoweekday() # 1=Mon ... 7=Sun
|
||||
current_time = now.strftime("%H:%M")
|
||||
|
||||
for block in config.get("schedule", []):
|
||||
if current_day not in block.get("days", []):
|
||||
continue
|
||||
start = block.get("start", "00:00")
|
||||
end = block.get("end", "23:59")
|
||||
|
||||
# Handle overnight blocks (e.g., 18:00 - 06:00)
|
||||
if start <= end:
|
||||
if start <= current_time <= end:
|
||||
return block
|
||||
else:
|
||||
if current_time >= start or current_time <= end:
|
||||
return block
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _get_stream_status():
|
||||
"""Check if music files are available for streaming."""
|
||||
music_dir = os.path.join(BASE_DIR, "media", "music")
|
||||
fallback_dir = os.path.join(BASE_DIR, "media", "fallback")
|
||||
count = 0
|
||||
for d in (music_dir, fallback_dir):
|
||||
if not os.path.isdir(d):
|
||||
continue
|
||||
for dirpath, _dirs, filenames in os.walk(d):
|
||||
count += sum(1 for f in filenames if f.lower().endswith(".mp3"))
|
||||
return {
|
||||
"online": count > 0,
|
||||
"tracks": count,
|
||||
}
|
||||
|
||||
|
||||
@bp.route("/status")
|
||||
def status():
|
||||
db = get_db()
|
||||
|
||||
queue_depth = db.execute(
|
||||
"SELECT COUNT(*) as c FROM queue WHERE played=0"
|
||||
).fetchone()["c"]
|
||||
|
||||
total_episodes = db.execute(
|
||||
"SELECT COUNT(*) as c FROM episodes"
|
||||
).fetchone()["c"]
|
||||
|
||||
active_feeds = db.execute(
|
||||
"SELECT COUNT(*) as c FROM feed_state"
|
||||
).fetchone()["c"]
|
||||
|
||||
stream = _get_stream_status()
|
||||
block = _get_current_schedule_block()
|
||||
|
||||
return jsonify({
|
||||
"stream": stream,
|
||||
"queue_depth": queue_depth,
|
||||
"total_episodes": total_episodes,
|
||||
"active_feeds": active_feeds,
|
||||
"current_block": {
|
||||
"name": block["name"],
|
||||
"folder": block["folder"],
|
||||
} if block else None,
|
||||
})
|
||||
Reference in New Issue
Block a user