#!/usr/bin/env python3 from __future__ import annotations import argparse import getpass import sys from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[1] if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) from app.db import SessionLocal, configure_database from app.notion_import import ( apply_import, extract_page_id, fetch_page_blocks, parse_notion_blocks, print_summary, ) def main() -> int: parser = argparse.ArgumentParser(description="一次性导入 Notion 搬家记录到当前 SQLite 数据库") parser.add_argument("--dry-run", action="store_true", help="只解析,不写数据库") parser.add_argument("--apply", action="store_true", help="真正写入数据库") args = parser.parse_args() mode = _resolve_mode(args) token = getpass.getpass("请输入 Notion API token: ").strip() if not token: print("未输入 token,已退出") return 1 page_url = input("请输入 Notion 页面完整 URL: ").strip() if not page_url: print("未输入页面 URL,已退出") return 1 try: page_id = extract_page_id(page_url) except ValueError as exc: print(f"页面 URL 无法识别: {exc}") return 1 print() print(f"正在读取 Notion page: {page_id}") try: blocks = fetch_page_blocks(token, page_id) except Exception as exc: print(f"读取 Notion page 失败: {exc}") return 1 print(f"已读取顶层及嵌套 blocks,总数约 {count_blocks(blocks)} 个") print("正在解析页面结构...") summary = parse_notion_blocks(blocks) print_summary(summary) if mode == "dry-run": print() print("dry-run 完成,未写入数据库。") return 0 print() print("这是一次性导入脚本,不建议在同一数据库上重复执行。") print("建议先备份当前 SQLite 数据库,再继续。") confirmed = input("确认执行导入?输入 yes 继续: ").strip().lower() if confirmed != "yes": print("已取消导入。") return 0 configure_database() db = SessionLocal() try: counts = apply_import(summary, db) except Exception as exc: db.rollback() print(f"导入失败,已回滚: {exc}") return 1 finally: db.close() print() print("导入完成") print(f"- 写入 Box: {counts['boxes']}") print(f"- 写入 Item: {counts['items']}") print(f"- 写入 SubItem: {counts['subitems']}") return 0 def _resolve_mode(args: argparse.Namespace) -> str: if args.apply and args.dry_run: raise SystemExit("请只选择一种模式:--dry-run 或 --apply") if args.apply: return "apply" return "dry-run" def count_blocks(blocks: list[dict]) -> int: total = 0 for block in blocks: total += 1 total += count_blocks(block.get("_children", [])) return total if __name__ == "__main__": raise SystemExit(main())