feat: initial implementation of navidrome-music-sync with Yandex, Spotify, Apple, YouTube support and Web UI

This commit is contained in:
Antigravity committed 2026-10-12 11:17:18 +03:00
1 parent 44c67ab49d
commit 5b6c2c72f7
23 files changed
+1445 -2

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
import os
from fastapi import FastAPI, Request, HTTPException
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
from typing import List, Dict, Any
from app.config import settings
from app.db import init_db, get_recent_tracks, get_tracks_count
from app.queue import sync_manager
app = FastAPI(title="Navidrome Music Sync", version="1.0.0")
# Mount static and templates
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
app.mount("/static", StaticFiles(directory=os.path.join(BASE_DIR, "static")), name="static")
templates = Jinja2Templates(directory=os.path.join(BASE_DIR, "templates"))
class DownloadRequest(BaseModel):
url: str
@app.on_event("startup")
def on_startup():
init_db()
@app.get("/")
def read_root(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
@app.post("/api/download")
async def start_download(req: DownloadRequest):
url = req.url.strip()
if not url:
raise HTTPException(status_code=400, detail="URL is required")
task = await sync_manager.start_sync_task(url)
return {"task_id": task.id, "status": task.status}
@app.post("/api/sync/yandex-likes")
async def sync_yandex_likes():
if not settings.YANDEX_MUSIC_TOKEN:
raise HTTPException(status_code=400, detail="Yandex Music Token is not configured.")
task = await sync_manager.start_sync_task("yandex:likes")
return {"task_id": task.id, "status": task.status}
@app.get("/api/tasks")
def list_tasks():
return list(sync_manager.tasks.values())
@app.get("/api/tasks/{task_id}")
def get_task(task_id: str):
if task_id not in sync_manager.tasks:
raise HTTPException(status_code=404, detail="Task not found")
return sync_manager.tasks[task_id]
@app.get("/api/history")
def get_history(limit: int = 50):
tracks = get_recent_tracks(limit)
total = get_tracks_count()
return {"total": total, "tracks": tracks}
@app.get("/api/health")
def healthcheck():
return {"status": "ok", "yandex_configured": bool(settings.YANDEX_MUSIC_TOKEN)}