scholarr/scripts/db/repair_publication_links.py

66 lines
1.9 KiB
Python
Executable file

#!/usr/bin/env python3
from __future__ import annotations
import argparse
import asyncio
import json
from app.db.session import get_session_factory
from app.services.dbops import run_publication_link_repair
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
description="Repair scholar-publication links for a user with audit logging.",
)
parser.add_argument("--user-id", type=int, required=True, help="Target user ID.")
parser.add_argument(
"--scholar-profile-id",
type=int,
action="append",
default=[],
help="Optional scholar_profile_id filter. Repeat for multiple values.",
)
parser.add_argument("--apply", action="store_true", help="Apply changes. Default is dry-run.")
parser.add_argument(
"--gc-orphan-publications",
action="store_true",
help="Delete publications with zero links after cleanup.",
)
parser.add_argument(
"--requested-by",
default="",
help="Operator identifier for audit logs (email/name/ticket).",
)
return parser
async def _run(args: argparse.Namespace) -> dict:
session_factory = get_session_factory()
async with session_factory() as db_session:
return await run_publication_link_repair(
db_session,
user_id=args.user_id,
scholar_profile_ids=args.scholar_profile_id,
dry_run=not args.apply,
gc_orphan_publications=args.gc_orphan_publications,
requested_by=args.requested_by,
)
def main() -> int:
parser = build_parser()
args = parser.parse_args()
try:
result = asyncio.run(_run(args))
except Exception as exc:
print(json.dumps({"status": "failed", "error": str(exc)}, indent=2))
return 1
print(json.dumps(result, indent=2))
return 0
if __name__ == "__main__":
raise SystemExit(main())