A lot of things updated.

Signed-off-by: Pavel Kirilin <win10@list.ru>
This commit is contained in:
2024-05-02 04:01:11 +02:00
parent 08c44219b0
commit 8559ec7a85
13 changed files with 2395 additions and 32 deletions

View File

@ -1,10 +1,11 @@
from pathlib import Path
from typing import Optional
from fastapi import FastAPI
from fastapi import FastAPI, HTTPException, Request, Response
from fastapi.staticfiles import StaticFiles
from typer import Typer, Argument
import uvicorn
from anime.routes import router
from starlette.middleware.base import BaseHTTPMiddleware
CURRENT_DIR = Path(__file__).parent
STATIC_DIR = CURRENT_DIR / "static"
@ -12,6 +13,20 @@ STATIC_DIR = CURRENT_DIR / "static"
cli = Typer()
async def response_formatter(request: Request, call_next):
try:
response = await call_next(request)
print(response)
except Exception as e:
response = Response(
status_code=500,
content={
"detail": str(e),
},
)
return response
@cli.command()
def run_app(
host: str = "0.0.0.0",
@ -33,7 +48,9 @@ def run_app(
check_dir=False,
),
)
app.add_middleware(BaseHTTPMiddleware, dispatch=response_formatter)
app.state.anime_dir = anime_dir
app.state.pid = None
uvicorn.run(app, host=host, port=port, workers=1)

View File

@ -1,5 +1,7 @@
import os
from pathlib import Path
import shutil
import subprocess
from fastapi import APIRouter, HTTPException, Request
from anime.dtos import KillRequest, PlayerOffsetRequest
@ -25,17 +27,54 @@ def start_watching(request: Request) -> None:
anime_dir = request.app.state.anime_dir
if not anime_dir:
raise HTTPException(status_code=400, detail="Anime directory is not set.")
os.chdir(anime_dir)
os.system("awatch")
os.chdir(CWD)
if request.app.state.pid:
try:
os.kill(request.app.state.pid, 0)
except OSError:
pass
else:
raise HTTPException(
status_code=400,
detail="Awatch is already running.",
)
awatch = shutil.which("awatch")
if awatch is None:
raise Exception(
"awatch command is not available. Please install awatch.\n"
"https://gitlab.le-memese.com/s3rius/awatch/"
)
ret = subprocess.Popen(
[awatch],
cwd=anime_dir,
)
request.app.state.pid = ret.pid
ret.wait()
request.app.state.pid = None
@router.post("/player/offset")
async def offset(req: PlayerOffsetRequest) -> None:
direction = "+" if req.forward else "-"
os.system(f"playerctl position {req.offset}{direction}")
playerctl = shutil.which("playerctl")
if playerctl is None:
raise HTTPException(
status_code=500,
detail="playerctl command is not available.",
)
subprocess.run(
[playerctl, "position", f"{req.offset}{direction}"],
check=False,
)
@router.post("/player/play-pause")
async def play_pause() -> None:
os.system("playerctl play-pause")
playerctl = shutil.which("playerctl")
if playerctl is None:
raise HTTPException(
status_code=500,
detail="playerctl command is not available.",
)
subprocess.run([playerctl, "play-pause"], check=False)

View File

@ -1,6 +1,7 @@
import os
from pathlib import Path
from shutil import copytree, rmtree
import shutil
import subprocess
CURRENT_DIR = Path(__file__).parent
@ -29,15 +30,19 @@ def build(setup_kwargs):
This script is useful for packaging the application.
"""
print("Starting building frontend ...")
pnpm_path = shutil.which("pnpm")
if pnpm_path is None:
raise Exception("pnpm command is not available. PLease install pnpm.")
with DirChanger(CURRENT_DIR / "frontend"):
ret_status = os.system("pnpm build")
if ret_status != 0:
raise Exception("Frontend build failed.")
subprocess.run(
[pnpm_path, "build"],
cwd=CURRENT_DIR / "frontend",
check=True,
)
print("Frontend build finished.")
rmtree(STATIC_OUTPUT_DIR, ignore_errors=True)
copytree(symlinks=True, src=DIST_DIR, dst=STATIC_OUTPUT_DIR)
shutil.rmtree(STATIC_OUTPUT_DIR, ignore_errors=True)
shutil.copytree(symlinks=True, src=DIST_DIR, dst=STATIC_OUTPUT_DIR)
return setup_kwargs

1
frontend/.gitignore vendored
View File

@ -11,6 +11,7 @@ node_modules
.DS_Store
dist
dist-ssr
dev-dist
coverage
*.local

View File

@ -1,13 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Anime</title>
<link rel="mask-icon" href="/mask-icon.svg" color="#FFFFFF">
<meta name="theme-color" content="#ffffff">
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

View File

@ -24,6 +24,7 @@
"eslint-plugin-vue": "^9.23.0",
"prettier": "^3.2.5",
"vite": "^5.2.8",
"vite-plugin-pwa": "^0.20.0",
"vite-plugin-vue-devtools": "^7.0.25"
}
}

2274
frontend/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

BIN
frontend/public/icon.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -1,5 +1,5 @@
<script setup>
import { Tabbar, TabbarItem, ActionBar, ActionBarButton } from 'vant';
import { ActionBar, ActionBarButton } from 'vant';
import { postRequest } from '@/utils'

View File

@ -1,3 +1,5 @@
import { showFailToast } from 'vant';
async function postRequest(url, data) {
const response = await fetch(url, {
method: 'POST',
@ -6,7 +8,13 @@ async function postRequest(url, data) {
},
body: JSON.stringify(data)
})
return response.json()
const resp_data = await response.json()
if (!response.ok) {
showFailToast({
message: resp_data.detail
})
}
return resp_data
}

View File

@ -2,11 +2,36 @@ import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
VitePWA({
manifest: {
name: 'Anime',
short_name: 'Anime',
start_url: '/',
theme_color: '#000000',
icons: [
{
src: '/pwa-192x192.jpg',
sizes: '192x192',
type: 'image/jpeg',
},
{
src: '/pwa-512x512.jpg',
sizes: '512x512',
type: 'image/jpeg',
}
]
},
devOptions: {
enabled: true,
},
registerType: "autoUpdate",
})
],
resolve: {
alias: {