Files
snoopy 6f551ba439 Initial release — MediaTracker v1.0
Dockerized media library scanner for NAS drives.
Identifies movies and series from filenames, fetches posters
via the public IMDB suggestion API (no key required), and
exposes a dark-themed web UI with multilingual search support.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 11:40:44 +00:00

99 lines
3.2 KiB
Python

from fastapi import APIRouter, HTTPException, Request
from database import ScanHistory, get_session
from scheduler import (
get_active_scan_id,
is_scan_running,
trigger_full_scan,
trigger_incremental_scan,
)
router = APIRouter(prefix="/api/scan", tags=["scan"])
@router.post("/full")
def start_full_scan(request: Request):
settings = request.app.state.settings
if is_scan_running():
raise HTTPException(status_code=409, detail="A scan is already running")
scan_id = trigger_full_scan(settings)
if scan_id is None:
raise HTTPException(status_code=409, detail="A scan is already running")
return {"scan_id": scan_id, "type": "full", "status": "running"}
@router.post("/incremental")
def start_incremental_scan(request: Request):
settings = request.app.state.settings
if is_scan_running():
raise HTTPException(status_code=409, detail="A scan is already running")
scan_id = trigger_incremental_scan(settings)
if scan_id is None:
raise HTTPException(status_code=409, detail="A scan is already running")
return {"scan_id": scan_id, "type": "incremental", "status": "running"}
@router.get("/status/{scan_id}")
def get_scan_status(scan_id: int):
session = get_session()
try:
record = session.query(ScanHistory).get(scan_id)
if record is None:
raise HTTPException(status_code=404, detail="Scan not found")
return {
"scan_id": record.id,
"type": record.scan_type,
"status": record.status,
"started_at": record.started_at.isoformat() if record.started_at else None,
"finished_at": record.finished_at.isoformat() if record.finished_at else None,
"files_found": record.files_found,
"files_added": record.files_added,
"files_removed": record.files_removed,
"files_unmatched": record.files_unmatched,
"error_message": record.error_message,
}
finally:
session.close()
@router.post("/fetch-alt-titles")
def fetch_alt_titles_now():
"""Trigger a Wikidata alt-title fetch in the background (no file scan)."""
def _run():
session = get_session()
try:
_fetch_alt_titles(session)
finally:
session.close()
threading.Thread(target=_run, daemon=True, name="alt-titles-fetch").start()
return {"status": "started"}
@router.get("/history")
def get_scan_history():
session = get_session()
try:
records = (
session.query(ScanHistory)
.order_by(ScanHistory.started_at.desc())
.limit(20)
.all()
)
return [
{
"scan_id": r.id,
"type": r.scan_type,
"status": r.status,
"started_at": r.started_at.isoformat() if r.started_at else None,
"finished_at": r.finished_at.isoformat() if r.finished_at else None,
"files_found": r.files_found,
"files_added": r.files_added,
"files_removed": r.files_removed,
"files_unmatched": r.files_unmatched,
"error_message": r.error_message,
}
for r in records
]
finally:
session.close()