import argparse import sys from app.config import load_config def _store(cfg): import os from photoflow.core import Store os.makedirs(cfg.data_dir, exist_ok=True) return Store(cfg.db_path).connect() def _immich(deps, cfg): if "immich" in deps: return deps["immich"] from photoflow.immich import ImmichClient return ImmichClient(cfg.immich_url, cfg.immich_api_key) def cmd_ingest(deps, *, date_from, date_to, tag, subset, full) -> int: cfg = deps["config"] store = _store(cfg) client = _immich(deps, cfg) from app.ingest import run_ingest res = run_ingest(client, store, cfg.thumbs_dir, date_from=date_from, date_to=date_to, tag=tag, subset=subset, full=full) store.close() print(f"Ingested {res['fetched']} asset(s); " f"{res['processed_marked']} already-processed.") return 0 def cmd_serve(deps) -> int: from app import create_app create_app(deps["config"]).run(host="0.0.0.0", port=8084) return 0 def build_parser() -> argparse.ArgumentParser: p = argparse.ArgumentParser(prog="categorize") sub = p.add_subparsers(dest="command", required=True) ing = sub.add_parser("ingest") ing.add_argument("--from", dest="date_from") ing.add_argument("--to", dest="date_to") ing.add_argument("--tag") ing.add_argument("--subset", type=int) ing.add_argument("--full", action="store_true", help="ignore incremental updatedAfter") cl = sub.add_parser("cluster") cl.add_argument("--gap-factor", type=float, default=6.0) sub.add_parser("serve") ap = sub.add_parser("apply") ap.add_argument("--yes", action="store_true", help="skip the confirmation prompt") return p def main(argv=None) -> int: args = build_parser().parse_args(argv) deps = {"config": load_config()} if args.command == "serve": return cmd_serve(deps) if args.command == "ingest": return cmd_ingest(deps, date_from=args.date_from, date_to=args.date_to, tag=args.tag, subset=args.subset, full=args.full) # cluster / apply are wired in later tasks. print(f"Command '{args.command}' is not implemented yet.") return 1 if __name__ == "__main__": sys.exit(main())