switch to grimmory as book web app and a more modern dashboard
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import logging
|
||||
import shutil
|
||||
import threading
|
||||
import time
|
||||
from pathlib import Path
|
||||
@@ -7,6 +6,7 @@ from pathlib import Path
|
||||
import config
|
||||
import db
|
||||
import extractor
|
||||
import grimmory as grimmory_module
|
||||
import sftp as sftp_module
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -33,20 +33,17 @@ def run_sync(limit: int | None = None) -> None:
|
||||
|
||||
_running = True
|
||||
run_id = db.start_sync_run()
|
||||
counters = dict(zips_found=0, zips_new=0, books_imported=0, books_errored=0)
|
||||
counters = dict(zips_found=0, zips_new=0, books_imported=0, books_skipped=0, books_errored=0)
|
||||
|
||||
try:
|
||||
log.info("Sync started (limit=%s)", limit)
|
||||
cfg = config.load()
|
||||
_validate_config(cfg)
|
||||
log.info("Config OK — work dir: %s, import dir: %s", cfg.work_dir, cfg.import_dir)
|
||||
log.info("Config OK — work dir: %s, bookdrop: %s", cfg.work_dir, cfg.grimmory.bookdrop_path)
|
||||
|
||||
work_dir = Path(cfg.work_dir)
|
||||
work_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
import_dir = Path(cfg.import_dir)
|
||||
import_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
log.info("Connecting to SFTP %s@%s:%s ...", cfg.sftp.user, cfg.sftp.host, cfg.sftp.port)
|
||||
new_zips = sftp_module.list_new_zips(cfg.sftp, max_results=limit)
|
||||
counters["zips_found"] = len(new_zips)
|
||||
@@ -71,6 +68,11 @@ def run_sync(limit: int | None = None) -> None:
|
||||
zip_status = "success"
|
||||
zip_error = None
|
||||
local_zip = None
|
||||
|
||||
# Insert zip row early so we have a zip_id for per-book records
|
||||
db.mark_zip_processed(remote_zip.remote_path, remote_zip.file_size, "running")
|
||||
zip_id = db.get_zip_id_by_path(remote_zip.remote_path)
|
||||
|
||||
try:
|
||||
t0 = time.monotonic()
|
||||
local_zip = sftp_module.download(cfg.sftp, remote_zip, str(work_dir / "downloads"))
|
||||
@@ -81,13 +83,26 @@ def run_sync(limit: int | None = None) -> None:
|
||||
log.info("Extract done in %.1fs — %d book(s)", time.monotonic() - t1, len(books))
|
||||
|
||||
for book in books:
|
||||
dest = import_dir / book.name
|
||||
if dest.exists():
|
||||
log.info("Skipping '%s' — already exists in import dir", book.name)
|
||||
else:
|
||||
shutil.move(str(book), str(dest))
|
||||
log.info("Moved '%s' → %s", book.name, import_dir)
|
||||
sha256 = grimmory_module.compute_sha256(book)
|
||||
if db.is_book_processed(sha256):
|
||||
log.info("Skipping '%s' — sha256 already processed", book.name)
|
||||
counters["books_skipped"] += 1
|
||||
db.record_book(zip_id, book.name, sha256, status="skipped")
|
||||
continue
|
||||
result = grimmory_module.place_book(
|
||||
book,
|
||||
cfg.grimmory.bookdrop_path,
|
||||
cfg.grimmory.url,
|
||||
cfg.grimmory.user,
|
||||
cfg.grimmory.password,
|
||||
sha256=sha256,
|
||||
)
|
||||
if result.status == "success":
|
||||
counters["books_imported"] += 1
|
||||
elif result.status == "skipped":
|
||||
counters["books_skipped"] += 1
|
||||
db.record_book(zip_id, book.name, result.sha256,
|
||||
status=result.status, error_msg=result.error_msg)
|
||||
|
||||
extractor.cleanup(work_dir / "extracted" / local_zip.stem)
|
||||
except Exception as e:
|
||||
@@ -127,7 +142,13 @@ def _validate_config(cfg) -> None:
|
||||
missing.append("SSH private key")
|
||||
if cfg.sftp.auth_method == "password" and not cfg.sftp.password:
|
||||
missing.append("SSH password")
|
||||
if not cfg.import_dir:
|
||||
missing.append("CWA import folder")
|
||||
if not cfg.grimmory.url:
|
||||
missing.append("Grimmory URL")
|
||||
if not cfg.grimmory.user:
|
||||
missing.append("Grimmory username")
|
||||
if not cfg.grimmory.password:
|
||||
missing.append("Grimmory password")
|
||||
if not cfg.grimmory.bookdrop_path:
|
||||
missing.append("Grimmory bookdrop path")
|
||||
if missing:
|
||||
raise ValueError(f"Missing configuration: {', '.join(missing)}")
|
||||
|
||||
Reference in New Issue
Block a user