Major overhaul to the theme and now functioning.

This commit is contained in:
2026-01-05 16:07:30 -05:00
parent 5823ca3c39
commit a475dfeab6
5218 changed files with 1643729 additions and 13229 deletions
@@ -0,0 +1,43 @@
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from typing import Optional, List
from ..downloader_manager import manager
router = APIRouter()
class DownloadRequest(BaseModel):
urls: List[str]
download_images: bool = True
download_videos: bool = True
max_workers: int = 3
force_overwrite: bool = False
class StatusResponse(BaseModel):
active: bool
status: str
downloaded: int
total: int
speed: float
eta: float
current_file: str
@router.post("/start")
def start_download(request: DownloadRequest):
try:
manager.start_download(request.urls, request.model_dump())
return {"message": "Download started"}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@router.post("/cancel")
def cancel_download():
manager.cancel_download()
return {"message": "Cancellation requested"}
@router.get("/status", response_model=StatusResponse)
def get_status():
return manager.progress
@router.get("/logs", response_model=List[str])
def get_logs():
return manager.logs
@@ -1,12 +1,18 @@
import os
import io
import mimetypes
import zipfile
import hashlib
import shutil
from fastapi import APIRouter, UploadFile, File, Request, Response
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from ..samba_manager import SambaManager
from ..config import settings
import os
import io
import mimetypes
import zipfile
# CBZ Cache Configuration
CACHE_DIR = "temp_cbz"
os.makedirs(CACHE_DIR, exist_ok=True)
class RenameRequest(BaseModel):
old_path: str
@@ -14,6 +20,32 @@ class RenameRequest(BaseModel):
router = APIRouter()
def get_cached_cbz_path(share_name: str, path: str):
"""Returns the local path to the cached CBZ file, downloading it if necessary."""
file_hash = hashlib.md5(f"{share_name}:{path}".encode()).hexdigest()
cache_path = os.path.join(CACHE_DIR, f"{file_hash}.cbz")
if not os.path.exists(cache_path):
# Check if we need to clean up cache? (Simple FIFO or size check could be added later)
# For now, we download.
manager = SambaManager(
settings.samba_server_ip,
share_name,
username=settings.samba_username,
password=settings.samba_password,
)
try:
with open(cache_path, "wb") as f:
manager.download_file(path, f)
except Exception as e:
# Clean up partial file
if os.path.exists(cache_path):
os.remove(cache_path)
raise e
finally:
manager.close()
return cache_path
@router.get("/list/{share_name}")
def list_files(share_name: str, path: str = "/"):
@@ -36,8 +68,23 @@ def delete_file(share_name: str, path: str):
username=settings.samba_username,
password=settings.samba_password,
)
result = manager.delete_file(path)
manager.close()
try:
# Check if it's a directory
attributes = manager.get_attributes(path)
if isinstance(attributes, dict) and "error" in attributes:
# If getting attributes fails, try deleting as file (maybe simple file)
# or return error. But standard delete_file tries deleteFiles.
result = manager.delete_file(path)
elif attributes.isDirectory:
result = manager.delete_directory_recursive(path)
else:
result = manager.delete_file(path)
except Exception as e:
result = {"error": str(e)}
finally:
manager.close()
return result
@@ -122,47 +169,39 @@ def view_file(share_name: str, path: str, request: Request):
@router.get("/cbz/list/{share_name}")
def list_cbz_contents(share_name: str, path: str):
manager = SambaManager(
settings.samba_server_ip,
share_name,
username=settings.samba_username,
password=settings.samba_password,
)
file_obj = io.BytesIO()
manager.download_file(path, file_obj)
manager.close()
file_obj.seek(0)
image_files = []
with zipfile.ZipFile(file_obj, 'r') as zip_ref:
for file_info in zip_ref.infolist():
if file_info.filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp')):
image_files.append(file_info.filename)
return sorted(image_files)
try:
cache_path = get_cached_cbz_path(share_name, path)
image_files = []
with zipfile.ZipFile(cache_path, 'r') as zip_ref:
for file_info in zip_ref.infolist():
if file_info.filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp')):
image_files.append(file_info.filename)
return sorted(image_files)
except Exception as e:
return Response(content=str(e), status_code=500)
@router.get("/cbz/image/{share_name}")
def get_cbz_image(share_name: str, path: str, image_name: str):
manager = SambaManager(
settings.samba_server_ip,
share_name,
username=settings.samba_username,
password=settings.samba_password,
)
file_obj = io.BytesIO()
manager.download_file(path, file_obj)
manager.close()
file_obj.seek(0)
with zipfile.ZipFile(file_obj, 'r') as zip_ref:
with zip_ref.open(image_name) as image_file:
image_data = io.BytesIO(image_file.read())
media_type, _ = mimetypes.guess_type(image_name)
if media_type is None:
media_type = "application/octet-stream"
try:
cache_path = get_cached_cbz_path(share_name, path)
return StreamingResponse(image_data, media_type=media_type)
# Open zip from cache
# We need to return a stream. We can read the specific file into BytesIO.
# This is fast since it's local disk read.
with zipfile.ZipFile(cache_path, 'r') as zip_ref:
with zip_ref.open(image_name) as image_file:
image_data = io.BytesIO(image_file.read())
media_type, _ = mimetypes.guess_type(image_name)
if media_type is None:
media_type = "application/octet-stream"
return StreamingResponse(image_data, media_type=media_type)
except Exception as e:
return Response(content=str(e), status_code=500)
@router.put("/files/rename/{share_name}")