feat: routes
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
"""Album endpoints."""
|
||||
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/albums", tags=["albums"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def list_albums() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{album_id}")
|
||||
async def get_album(album_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{album_id}/tracks")
|
||||
async def get_album_tracks(album_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{album_id}/cover")
|
||||
async def get_album_cover(album_id: uuid.UUID) -> Any: ...
|
||||
@@ -0,0 +1,28 @@
|
||||
"""Artist endpoints."""
|
||||
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/artists", tags=["artists"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def list_artists() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{artist_id}")
|
||||
async def get_artist(artist_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{artist_id}/albums")
|
||||
async def get_artist_albums(artist_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{artist_id}/tracks")
|
||||
async def get_artist_tracks(artist_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{artist_id}/similar")
|
||||
async def get_similar_artists(artist_id: uuid.UUID) -> Any: ...
|
||||
@@ -0,0 +1,36 @@
|
||||
"""Download job endpoints. Heavy work is dispatched to arq workers."""
|
||||
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/downloads", tags=["downloads"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def list_downloads() -> Any: ...
|
||||
|
||||
|
||||
@router.post("")
|
||||
async def create_download() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{job_id}")
|
||||
async def get_download(job_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.delete("/{job_id}")
|
||||
async def cancel_download(job_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.post("/{job_id}/retry")
|
||||
async def retry_download(job_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.post("/pause")
|
||||
async def pause_downloads() -> Any: ...
|
||||
|
||||
|
||||
@router.post("/resume")
|
||||
async def resume_downloads() -> Any: ...
|
||||
@@ -0,0 +1,15 @@
|
||||
"""Playback history endpoints."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/history", tags=["history"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def get_history() -> Any: ...
|
||||
|
||||
|
||||
@router.post("")
|
||||
async def record_history() -> Any: ...
|
||||
@@ -0,0 +1,19 @@
|
||||
"""Like endpoints. Likes are an append-only event-log — never updated in place."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/likes", tags=["likes"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def get_likes() -> Any: ...
|
||||
|
||||
|
||||
@router.post("")
|
||||
async def add_like() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/state")
|
||||
async def get_likes_state() -> Any: ...
|
||||
@@ -0,0 +1,48 @@
|
||||
"""Playlist endpoints."""
|
||||
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/playlists", tags=["playlists"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def list_playlists() -> Any: ...
|
||||
|
||||
|
||||
@router.post("")
|
||||
async def create_playlist() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{playlist_id}")
|
||||
async def get_playlist(playlist_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.patch("/{playlist_id}")
|
||||
async def update_playlist(playlist_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.delete("/{playlist_id}")
|
||||
async def delete_playlist(playlist_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{playlist_id}/tracks")
|
||||
async def get_playlist_tracks(playlist_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.post("/{playlist_id}/tracks")
|
||||
async def add_playlist_tracks(playlist_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.delete("/{playlist_id}/tracks/{track_id}")
|
||||
async def remove_playlist_track(playlist_id: uuid.UUID, track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.put("/{playlist_id}/tracks/reorder")
|
||||
async def reorder_playlist_tracks(playlist_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{playlist_id}/cover")
|
||||
async def get_playlist_cover(playlist_id: uuid.UUID) -> Any: ...
|
||||
@@ -0,0 +1,15 @@
|
||||
"""Radio / continuous-mix endpoints. Degrades gracefully when ML service is down."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/radio", tags=["radio"])
|
||||
|
||||
|
||||
@router.post("")
|
||||
async def start_radio() -> Any: ...
|
||||
|
||||
|
||||
@router.post("/next")
|
||||
async def next_radio_track() -> Any: ...
|
||||
@@ -0,0 +1,15 @@
|
||||
"""Search endpoints: global and library-scoped."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/search", tags=["search"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def search() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/library")
|
||||
async def search_library() -> Any: ...
|
||||
@@ -0,0 +1,19 @@
|
||||
"""External source endpoints (yt-dlp etc.)."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/sources", tags=["sources"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def list_sources() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{source}/search")
|
||||
async def search_source(source: str) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{source}/health")
|
||||
async def source_health(source: str) -> Any: ...
|
||||
@@ -0,0 +1,27 @@
|
||||
"""Storage analysis and cleanup endpoints."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/storage", tags=["storage"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def get_storage_stats() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/duplicates")
|
||||
async def get_duplicates() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/broken")
|
||||
async def get_broken_files() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/missing-metadata")
|
||||
async def get_missing_metadata() -> Any: ...
|
||||
|
||||
|
||||
@router.post("/cleanup")
|
||||
async def run_cleanup() -> Any: ...
|
||||
@@ -0,0 +1,20 @@
|
||||
"""Audio streaming endpoints: direct stream and HLS."""
|
||||
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/stream", tags=["streaming"])
|
||||
|
||||
|
||||
@router.get("/{track_id}")
|
||||
async def stream_track(track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{track_id}/hls/playlist.m3u8")
|
||||
async def hls_playlist(track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{track_id}/hls/{segment}")
|
||||
async def hls_segment(track_id: uuid.UUID, segment: str) -> Any: ...
|
||||
@@ -0,0 +1,15 @@
|
||||
"""Client sync endpoints (offline-first event log)."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/sync", tags=["sync"])
|
||||
|
||||
|
||||
@router.get("/changes")
|
||||
async def get_changes() -> Any: ...
|
||||
|
||||
|
||||
@router.post("/push")
|
||||
async def push_changes() -> Any: ...
|
||||
@@ -0,0 +1,48 @@
|
||||
"""Track endpoints (library CRUD, similarity, optimization, cover, metadata, streaming)."""
|
||||
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/tracks", tags=["tracks"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def list_tracks() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{track_id}")
|
||||
async def get_track(track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.patch("/{track_id}")
|
||||
async def update_track(track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.delete("/{track_id}")
|
||||
async def delete_track(track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{track_id}/similar")
|
||||
async def get_similar_tracks(track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.post("/{track_id}/optimize")
|
||||
async def optimize_track(track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{track_id}/cover")
|
||||
async def get_track_cover(track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.post("/{track_id}/metadata/enrich")
|
||||
async def enrich_metadata(track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.get("/{track_id}/metadata/matches")
|
||||
async def get_metadata_matches(track_id: uuid.UUID) -> Any: ...
|
||||
|
||||
|
||||
@router.put("/{track_id}/metadata")
|
||||
async def set_metadata(track_id: uuid.UUID) -> Any: ...
|
||||
@@ -0,0 +1,11 @@
|
||||
"""Local file upload endpoint."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/upload", tags=["upload"])
|
||||
|
||||
|
||||
@router.post("")
|
||||
async def upload_file() -> Any: ...
|
||||
@@ -0,0 +1,23 @@
|
||||
"""User settings endpoints, including scrobbling configuration."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter(prefix="/settings", tags=["settings"])
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def get_settings() -> Any: ...
|
||||
|
||||
|
||||
@router.patch("")
|
||||
async def update_settings() -> Any: ...
|
||||
|
||||
|
||||
@router.get("/scrobbling")
|
||||
async def get_scrobbling_settings() -> Any: ...
|
||||
|
||||
|
||||
@router.put("/scrobbling")
|
||||
async def set_scrobbling_settings() -> Any: ...
|
||||
Reference in New Issue
Block a user