116 lines
3.7 KiB
Python
116 lines
3.7 KiB
Python
from fastapi import APIRouter, HTTPException, WebSocket, WebSocketDisconnect
|
|
from pydantic import BaseModel
|
|
from typing import List, Optional
|
|
import asyncio
|
|
import os
|
|
from ..comics_manager import ComicsManager
|
|
from ..config import settings
|
|
from ..samba_manager import SambaManager
|
|
from ..tasks import task_organize_comics, task_move_comics, task_update_metadata, task_sort_by_artist
|
|
|
|
router = APIRouter()
|
|
|
|
class MoveRequest(BaseModel):
|
|
series_names: List[str]
|
|
destination_share: Optional[str] = "comics"
|
|
destination_path: Optional[str] = "/manga"
|
|
|
|
class MetadataUpdateRequest(BaseModel):
|
|
target_path: Optional[str] = "/comics/manga"
|
|
force_update: Optional[bool] = False
|
|
|
|
class FolderScanRequest(BaseModel):
|
|
root_path: Optional[str] = "/comics/manga"
|
|
threshold: float = 0.9
|
|
|
|
class DeleteFolderRequest(BaseModel):
|
|
folder_path: str
|
|
|
|
class SortRequest(BaseModel):
|
|
root_path: Optional[str] = "/comics/manga"
|
|
|
|
def get_samba_manager(share="isolation"):
|
|
return SambaManager(
|
|
settings.samba_server_ip,
|
|
share,
|
|
settings.samba_username,
|
|
settings.samba_password,
|
|
)
|
|
|
|
@router.post("/organize")
|
|
def organize_comics():
|
|
task = task_organize_comics()
|
|
return {"message": f"Organization queued (Task ID: {task.id}). Check logs."}
|
|
|
|
@router.get("/pending")
|
|
def get_pending_comics():
|
|
manager = ComicsManager()
|
|
samba_manager = get_samba_manager("isolation")
|
|
try:
|
|
return manager.get_pending_comics(samba_manager)
|
|
finally:
|
|
samba_manager.close()
|
|
|
|
@router.post("/move")
|
|
def move_comics(request: MoveRequest):
|
|
task = task_move_comics(request.series_names, request.destination_share, request.destination_path)
|
|
return {"message": f"Move queued (Task ID: {task.id}). Check logs."}
|
|
|
|
@router.post("/update_metadata")
|
|
def update_metadata(request: MetadataUpdateRequest):
|
|
task = task_update_metadata(request.target_path, request.force_update)
|
|
return {"message": f"Metadata update queued (Task ID: {task.id}). Check logs."}
|
|
|
|
@router.post("/folders/scan")
|
|
def scan_folders(request: FolderScanRequest):
|
|
# This remains synchronous to return results immediately to UI
|
|
manager = ComicsManager()
|
|
samba_manager = get_samba_manager("isolation")
|
|
try:
|
|
groups = manager.find_similar_folders(samba_manager, request.root_path, request.threshold)
|
|
return groups
|
|
finally:
|
|
samba_manager.close()
|
|
|
|
@router.post("/folders/delete")
|
|
def delete_folder(request: DeleteFolderRequest):
|
|
manager = ComicsManager()
|
|
samba_manager = get_samba_manager("isolation")
|
|
try:
|
|
return manager.delete_folder(samba_manager, request.folder_path)
|
|
finally:
|
|
samba_manager.close()
|
|
|
|
@router.post("/sort_by_artist")
|
|
def sort_by_artist(request: SortRequest):
|
|
task = task_sort_by_artist(request.root_path)
|
|
return {"message": f"Sort by Artist queued (Task ID: {task.id}). Check logs."}
|
|
|
|
@router.websocket("/ws/logs")
|
|
async def websocket_endpoint(websocket: WebSocket):
|
|
await websocket.accept()
|
|
file_path = "logs/comics_organization.log"
|
|
|
|
# Ensure file exists
|
|
if not os.path.exists(file_path):
|
|
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
|
with open(file_path, "w") as f: f.write("")
|
|
|
|
try:
|
|
with open(file_path, "r") as f:
|
|
# Send last 20 lines for context
|
|
lines = f.readlines()
|
|
for line in lines[-20:]:
|
|
await websocket.send_text(line)
|
|
|
|
# Follow the file
|
|
f.seek(0, 2)
|
|
while True:
|
|
line = f.readline()
|
|
if line:
|
|
await websocket.send_text(line)
|
|
else:
|
|
await asyncio.sleep(0.1)
|
|
except WebSocketDisconnect:
|
|
pass
|