a8ec7b80de
---ci--- project: inboxos phase: 1 milestone: v1.4 status: execute wave: 2 tasks: [T3, T4, T5, T6, T7, T8] ---/ci---
85 lines
2.6 KiB
Python
Executable File
85 lines
2.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Reclassify MIDs between modules.
|
|
|
|
v1.4 REQ-INB-44.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import csv
|
|
import json
|
|
import os
|
|
import sys
|
|
from typing import Iterable
|
|
|
|
import requests
|
|
|
|
|
|
NOCODB_BASE_URL = os.environ.get("NOCODB_BASE_URL", "http://localhost:8080")
|
|
NOCODB_API_TOKEN = os.environ.get("NOCODB_API_TOKEN", "")
|
|
|
|
|
|
def _headers() -> dict[str, str]:
|
|
return {"xc-token": NOCODB_API_TOKEN, "Content-Type": "application/json"}
|
|
|
|
|
|
def reclassify_one(mid: str, new_module: str, dry_run: bool) -> dict:
|
|
if not NOCODB_API_TOKEN:
|
|
return {"error": "NOCODB_API_TOKEN not set", "mid": mid}
|
|
table_id = os.environ.get(f"NOCODB_TABLE_{new_module.upper()}", "")
|
|
if not table_id:
|
|
return {"error": f"NOCODB_TABLE_{new_module.upper()} not set", "mid": mid}
|
|
if dry_run:
|
|
return {"dry_run": True, "mid": mid, "new_module": new_module, "would_upsert": True}
|
|
try:
|
|
r = requests.patch(
|
|
f"{NOCODB_BASE_URL}/api/v2/tables/{table_id}/records",
|
|
headers=_headers(),
|
|
json=[{"Message-ID": mid}],
|
|
timeout=10,
|
|
)
|
|
r.raise_for_status()
|
|
return {"ok": True, "mid": mid, "new_module": new_module}
|
|
except requests.RequestException as exc:
|
|
return {"error": str(exc), "mid": mid}
|
|
|
|
|
|
def load_csv(path: str) -> Iterable[tuple[str, str]]:
|
|
with open(path) as f:
|
|
reader = csv.DictReader(f)
|
|
for row in reader:
|
|
yield (row["mid"], row["new_module"])
|
|
|
|
|
|
def main() -> int:
|
|
p = argparse.ArgumentParser(description="Reclassify MIDs between modules")
|
|
g = p.add_mutually_exclusive_group(required=True)
|
|
g.add_argument("--csv", help="CSV with mid,new_module rows")
|
|
g.add_argument("--mid", help="Single Message-ID")
|
|
p.add_argument("--new-module", help="Target module (when --mid is used)")
|
|
p.add_argument("--dry-run", action="store_true", default=True)
|
|
p.add_argument("--confirm", action="store_true", help="Actually write")
|
|
args = p.parse_args()
|
|
|
|
if args.csv:
|
|
pairs = list(load_csv(args.csv))
|
|
else:
|
|
if not args.new_module:
|
|
sys.stderr.write("--new-module required with --mid\n")
|
|
return 1
|
|
pairs = [(args.mid, args.new_module)]
|
|
|
|
if not args.confirm and not args.dry_run:
|
|
sys.stderr.write("Refusing to run without --dry-run or --confirm.\n")
|
|
return 1
|
|
|
|
dry_run = not args.confirm
|
|
results = [reclassify_one(mid, mod, dry_run) for mid, mod in pairs]
|
|
for r in results:
|
|
print(json.dumps(r))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|