import dataclasses from typing import Annotated from fastapi import HTTPException, Request from fastapi.params import Form from fastapi.responses import HTMLResponse from folkugat_web.api.router import get_router from folkugat_web.fragments import temes from folkugat_web.fragments.tema import scores as scores_fragments from folkugat_web.services import auth, files from folkugat_web.services.lilypond import build as lilypond_build from folkugat_web.services.lilypond import render as lilypond_render from folkugat_web.services.lilypond import source as lilypond_source from folkugat_web.services.temes import scores as scores_service router = get_router() @router.get("/api/tema/{tema_id}/score/{score_id}") def score(request: Request, logged_in: auth.LoggedIn, tema_id: int, score_id: int): score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id) if not score: raise HTTPException(status_code=404, detail="Could not find lyric!") return scores_fragments.score(request=request, logged_in=logged_in, score=score) @router.put("/api/tema/{tema_id}/score/{score_id}") async def set_score( request: Request, logged_in: auth.RequireLogin, tema_id: int, score_id: int, title: Annotated[str, Form()], source: Annotated[str, Form()], ): source = source.strip() score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id) if not score: raise HTTPException(status_code=404, detail="Could not find lyric!") new_score = await scores_service.render_score(score=score, title=title, source=source) scores_service.update_score(score=new_score) files.clean_orphan_files() return scores_fragments.score(request=request, logged_in=logged_in, score=new_score) @router.post("/api/tema/{tema_id}/score") def add_score( request: Request, logged_in: auth.RequireLogin, tema_id: int, ): score = scores_service.create_score(tema_id=tema_id) return scores_fragments.score_editor( request=request, logged_in=logged_in, score=score, ) @router.delete("/api/tema/{tema_id}/score/{score_id}") def delete_score(request: Request, logged_in: auth.RequireLogin, tema_id: int, score_id: int): scores_service.delete_score(score_id=score_id, tema_id=tema_id) files.clean_orphan_files() return HTMLResponse() @router.get("/api/tema/{tema_id}/editor/score/{score_id}") def score_editor( request: Request, logged_in: auth.RequireLogin, tema_id: int, score_id: int, ): score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id) if not score: raise HTTPException(status_code=404, detail="Could not find lyric!") return scores_fragments.score_editor( request=request, logged_in=logged_in, score=score, ) @router.post("/api/tema/{tema_id}/editor/score/{score_id}/render") async def render( request: Request, _: auth.RequireLogin, tema_id: int, score_id: int, source: Annotated[str, Form()], ): tune = lilypond_build.tune_from_tema_id(tema_id=tema_id, score_source=source) full_source = lilypond_source.tune_source(tune=tune) png_result = await lilypond_render.render( source=full_source, output=lilypond_render.RenderOutput.PNG_CROPPED, ) if output_filename := png_result.result: score_render_url = files.get_db_file_path(output_filename) return temes.score_render(request=request, score_id=score_id, score_render_url=score_render_url) else: return temes.score_render(request=request, score_id=score_id, errors=png_result.error) @router.put("/api/tema/{tema_id}/score/{score_id}/show") async def show_score( request: Request, logged_in: auth.RequireLogin, tema_id: int, score_id: int, ): score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id) if not score: raise HTTPException(status_code=404, detail="Could not find lyric!") new_score = dataclasses.replace(score, hidden=False) scores_service.update_score(score=new_score) return scores_fragments.score(request=request, logged_in=logged_in, score=new_score) @router.put("/api/tema/{tema_id}/score/{score_id}/hide") async def hide_score( request: Request, logged_in: auth.RequireLogin, tema_id: int, score_id: int, ): score = scores_service.get_score_by_id(score_id=score_id, tema_id=tema_id) if not score: raise HTTPException(status_code=404, detail="Could not find lyric!") new_score = dataclasses.replace(score, hidden=True) scores_service.update_score(score=new_score) return scores_fragments.score(request=request, logged_in=logged_in, score=new_score)