check for doubles
This commit is contained in:
@@ -214,6 +214,51 @@ async def delete_book_api(book_id: int):
|
||||
return {"ok": ok, "message": message}
|
||||
|
||||
|
||||
_dedup_state: dict = {"running": False, "deleted": 0, "failed": 0, "total": 0, "done": False, "error": None}
|
||||
|
||||
|
||||
def _run_dedup():
|
||||
global _dedup_state
|
||||
try:
|
||||
cfg = config.load()
|
||||
log.info("Dedup: fetching all books ...")
|
||||
books = fetch_all_books(cfg.calibre)
|
||||
groups = find_duplicate_groups(books)
|
||||
to_delete = [b for group in groups for b in sorted(group, key=lambda x: x.get("id", 0))[1:]]
|
||||
_dedup_state.update({"total": len(to_delete), "deleted": 0, "failed": 0})
|
||||
log.info("Dedup: %d duplicate(s) to delete across %d group(s)", len(to_delete), len(groups))
|
||||
for book in to_delete:
|
||||
ok, msg = delete_book(cfg.calibre, book["id"])
|
||||
if ok:
|
||||
_dedup_state["deleted"] += 1
|
||||
else:
|
||||
_dedup_state["failed"] += 1
|
||||
log.warning("Dedup: failed to delete book %d: %s", book["id"], msg)
|
||||
if _dedup_state["deleted"] % 10 == 0:
|
||||
log.info("Dedup progress: %d / %d deleted", _dedup_state["deleted"], _dedup_state["total"])
|
||||
log.info("Dedup done: %d deleted, %d failed", _dedup_state["deleted"], _dedup_state["failed"])
|
||||
except Exception as e:
|
||||
log.error("Dedup error: %s", e)
|
||||
_dedup_state["error"] = str(e)
|
||||
finally:
|
||||
_dedup_state["running"] = False
|
||||
_dedup_state["done"] = True
|
||||
|
||||
|
||||
@app.post("/api/delete_duplicates")
|
||||
async def delete_duplicates_api(background_tasks: BackgroundTasks):
|
||||
if _dedup_state["running"]:
|
||||
return {"ok": False, "message": "Already running"}
|
||||
_dedup_state.update({"running": True, "deleted": 0, "failed": 0, "total": 0, "done": False, "error": None})
|
||||
background_tasks.add_task(_run_dedup)
|
||||
return {"ok": True, "message": "Started"}
|
||||
|
||||
|
||||
@app.get("/api/delete_duplicates/status")
|
||||
async def delete_duplicates_status():
|
||||
return _dedup_state
|
||||
|
||||
|
||||
@app.get("/api/debug/calibre_books")
|
||||
async def debug_calibre_books():
|
||||
"""Show raw Calibre-Web listbooks response shape so we can identify field names."""
|
||||
|
||||
Reference in New Issue
Block a user