Add --import-qr to run the QR->CSV step before importing

Wrap the QR decode/append step behind --import-qr on the importer so a
single command runs the whole pipeline: decode QR images, append only
new credentials to the CSV (deduped on otpauth://, existing entries
silently skipped), then validate and import. QR folder defaults to the
CSV's folder; override with --qr-images. Refactor qr_to_sheet into
reusable collect_candidates / apply_new_candidates / run_qr_import.
This commit is contained in:
2026-07-08 15:31:03 -07:00
parent 0fad68b9f6
commit a8a405600c
4 changed files with 109 additions and 37 deletions

View File

@@ -675,6 +675,11 @@ def parse_args(argv=None):
p.add_argument("--memlog", default=DEFAULT_MEMLOG,
help=f"profiling CSV path (default: {DEFAULT_MEMLOG})")
p.add_argument("--password", help="applet password (else prompted if locked)")
p.add_argument("--import-qr", action="store_true",
help="first decode QR images and append new credentials to the "
"CSV (deduped on otpauth://), then import the CSV")
p.add_argument("--qr-images", metavar="DIR",
help="QR image folder for --import-qr (default: the folder of --input)")
p.add_argument("--reset", action="store_true",
help="wipe all credentials and any password, then exit")
p.add_argument("--set-password", metavar="PASS",
@@ -707,6 +712,15 @@ def main(argv=None):
print(f"Applet reset on '{reader}' (all credentials and any password wiped).")
return 0
# 0. Optionally decode QR images into the CSV first (stage 1 of the pipeline).
if args.import_qr:
from qr_to_sheet import run_qr_import, print_qr_summary
images_dir = args.qr_images or os.path.dirname(os.path.abspath(args.input)) or "."
print(f"QR import: {images_dir} -> {args.input}")
summary = run_qr_import(images_dir, args.input, dry_run=args.dry_run)
print_qr_summary(summary, args.input, args.dry_run)
print()
# 1. Load + validate BEFORE touching any reader.
creds = load_credentials(args.input)
problems = validate_input(creds)