Files

110 lines
3.0 KiB
Python
Raw Permalink Normal View History

2026-04-19 14:28:00 +02:00
#!/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())