Compare commits
2
Commits
de0d360a3c
...
00b841fa67
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00b841fa67 | ||
|
|
3fb2b34587 |
@@ -913,8 +913,18 @@ def scan_one(path):
|
|||||||
p = Path(path)
|
p = Path(path)
|
||||||
if not p.exists(): data = {"error": f"Datei nicht gefunden: {p}"}
|
if not p.exists(): data = {"error": f"Datei nicht gefunden: {p}"}
|
||||||
else:
|
else:
|
||||||
try: data = run_ffprobe(str(p)); log.info("Gescannt: %s", p)
|
try:
|
||||||
except Exception as exc: data = {"error": str(exc)}; log.error("Scanfehler für %s: %s", p, error_summary(exc))
|
data = run_ffprobe(str(p)); log.info("Gescannt: %s", p)
|
||||||
|
except Exception as exc:
|
||||||
|
# Cache failed probes as completed attempts. A changed mtime will
|
||||||
|
# invalidate this entry automatically and trigger a retry later.
|
||||||
|
data = {
|
||||||
|
"scanner_version": SCANNER_VERSION,
|
||||||
|
"audio_languages": [], "subtitle_languages": [],
|
||||||
|
"external_subtitle_files": [str(file) for file in external_subtitle_files(str(p))],
|
||||||
|
"video_codec": "—", "size": 0, "error": error_summary(exc),
|
||||||
|
}
|
||||||
|
log.error("Scanfehler für %s: %s", p, error_summary(exc))
|
||||||
mtime = p.stat().st_mtime
|
mtime = p.stat().st_mtime
|
||||||
con = db(); con.execute("INSERT INTO media_cache(path,mtime,data,scanned_at) VALUES(?,?,?,?) ON CONFLICT(path) DO UPDATE SET mtime=excluded.mtime,data=excluded.data,scanned_at=excluded.scanned_at", (str(p), mtime, json.dumps(data), datetime.utcnow().isoformat())); con.commit(); con.close()
|
con = db(); con.execute("INSERT INTO media_cache(path,mtime,data,scanned_at) VALUES(?,?,?,?) ON CONFLICT(path) DO UPDATE SET mtime=excluded.mtime,data=excluded.data,scanned_at=excluded.scanned_at", (str(p), mtime, json.dumps(data), datetime.utcnow().isoformat())); con.commit(); con.close()
|
||||||
return data
|
return data
|
||||||
@@ -996,7 +1006,7 @@ def sonarr_groups():
|
|||||||
"category":category_key, "category_label":category_label})
|
"category":category_key, "category_label":category_label})
|
||||||
return sorted(groups, key=lambda x: x["title"].lower())
|
return sorted(groups, key=lambda x: x["title"].lower())
|
||||||
|
|
||||||
def start_scan(source, force=False, rows_snapshot=None, series_snapshot=None):
|
def start_scan(source, force=False, rows_snapshot=None, series_snapshot=None, pending_only=False):
|
||||||
with job_lock:
|
with job_lock:
|
||||||
if jobs[source]["state"] == "running" or (jobs[source]["state"] in ("done", "error") and not force): return
|
if jobs[source]["state"] == "running" or (jobs[source]["state"] in ("done", "error") and not force): return
|
||||||
jobs[source] = {"state":"running", "total":0, "done":0, "error":None}
|
jobs[source] = {"state":"running", "total":0, "done":0, "error":None}
|
||||||
@@ -1005,16 +1015,16 @@ def start_scan(source, force=False, rows_snapshot=None, series_snapshot=None):
|
|||||||
paths = []
|
paths = []
|
||||||
if source == "radarr":
|
if source == "radarr":
|
||||||
for row in rows_snapshot if rows_snapshot is not None else radarr_rows():
|
for row in rows_snapshot if rows_snapshot is not None else radarr_rows():
|
||||||
if row["local_path"] != "—" and row["pending"]: paths.append(row["local_path"])
|
if row["local_path"] != "—" and row["pending"] and not row.get("downloading"): paths.append(row["local_path"])
|
||||||
elif source == "sonarr":
|
elif source == "sonarr":
|
||||||
for group in series_snapshot if series_snapshot is not None else sonarr_groups():
|
for group in series_snapshot if series_snapshot is not None else sonarr_groups():
|
||||||
paths.extend(r["local_path"] for r in group["episodes"] if r["local_path"] != "—" and r["pending"])
|
paths.extend(r["local_path"] for r in group["episodes"] if r["local_path"] != "—" and r["pending"] and not r.get("downloading"))
|
||||||
else:
|
else:
|
||||||
for row in rows_snapshot if rows_snapshot is not None else radarr_rows():
|
for row in rows_snapshot if rows_snapshot is not None else radarr_rows():
|
||||||
if row["local_path"] != "—" and is_german_review_candidate(row) and not has_german_track(row): paths.append(row["local_path"])
|
if row["local_path"] != "—" and is_german_review_candidate(row) and not row.get("downloading") and not has_german_track(row) and (not pending_only or row.get("pending")): paths.append(row["local_path"])
|
||||||
if SONARR_URL and SONARR_API_KEY:
|
if SONARR_URL and SONARR_API_KEY:
|
||||||
for group in series_snapshot if series_snapshot is not None else sonarr_groups():
|
for group in series_snapshot if series_snapshot is not None else sonarr_groups():
|
||||||
paths.extend(r["local_path"] for r in group["episodes"] if r["local_path"] != "—" and is_german_review_candidate(r) and not has_german_track(r))
|
paths.extend(r["local_path"] for r in group["episodes"] if r["local_path"] != "—" and is_german_review_candidate(r) and not r.get("downloading") and not has_german_track(r) and (not pending_only or r.get("pending")))
|
||||||
with job_lock: jobs[source]["total"] = len(paths)
|
with job_lock: jobs[source]["total"] = len(paths)
|
||||||
futures = [scan_executor.submit(scan_one, path) for path in paths]
|
futures = [scan_executor.submit(scan_one, path) for path in paths]
|
||||||
for future in as_completed(futures):
|
for future in as_completed(futures):
|
||||||
@@ -1057,14 +1067,14 @@ def refresh_library_cache():
|
|||||||
if series and any(row.get("pending") for group in series for row in group["episodes"]):
|
if series and any(row.get("pending") for group in series for row in group["episodes"]):
|
||||||
start_scan("sonarr", force=True, series_snapshot=series)
|
start_scan("sonarr", force=True, series_snapshot=series)
|
||||||
needs_missing_scan = any(
|
needs_missing_scan = any(
|
||||||
row.get("local_path") != "—" and is_german_review_candidate(row) and not has_german_track(row)
|
row.get("local_path") != "—" and is_german_review_candidate(row) and row.get("pending") and not has_german_track(row)
|
||||||
for row in rows
|
for row in rows
|
||||||
) or any(
|
) or any(
|
||||||
episode.get("local_path") != "—" and is_german_review_candidate(episode) and not has_german_track(episode)
|
episode.get("local_path") != "—" and is_german_review_candidate(episode) and episode.get("pending") and not has_german_track(episode)
|
||||||
for group in series for episode in group["episodes"]
|
for group in series for episode in group["episodes"]
|
||||||
)
|
)
|
||||||
if needs_missing_scan:
|
if needs_missing_scan:
|
||||||
start_scan("missing", force=True, rows_snapshot=rows, series_snapshot=series)
|
start_scan("missing", force=True, rows_snapshot=rows, series_snapshot=series, pending_only=True)
|
||||||
log.info("Bibliotheks-Sync abgeschlossen: %s Filme, %s Serien", len(rows), len(series))
|
log.info("Bibliotheks-Sync abgeschlossen: %s Filme, %s Serien", len(rows), len(series))
|
||||||
|
|
||||||
def background_library_sync():
|
def background_library_sync():
|
||||||
|
|||||||
Reference in New Issue
Block a user