slack-sieve/scripts/preset-skips.py
ilia 1ce803fc9c Initial import: Slack export triage UI for Mattermost migration.
Web UI for channel/message cherry-pick, attachment preview, hydrate script,
and workspace skip presets.
2026-05-29 13:53:28 -04:00

131 lines
4.1 KiB
Python
Executable File

#!/usr/bin/env python3
"""Pre-mark channels as skip in manifest.json using a JSON preset file."""
from __future__ import annotations
import json
import sys
from datetime import datetime, timezone
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
MANIFEST_PATH = REPO_ROOT / "manifest.json"
DEFAULT_PRESET = REPO_ROOT / "presets" / "levkin-skips.json"
DEFAULT_EXPORT = Path.home() / "Downloads/Levkin Slack export enriched"
def load_preset(path: Path) -> dict:
data = json.loads(path.read_text(encoding="utf-8"))
skip_a = set(data.get("tier_a") or [])
skip_b = set(data.get("tier_b") or [])
skip_other = set(data.get("other") or [])
return {
"skip_all": skip_a | skip_b | skip_other,
"tier_a": skip_a,
"tier_b": skip_b,
"review_priority": data.get("review_priority") or [],
"review_later": data.get("review_later") or [],
}
def channel_entry_skip(notes: str) -> dict:
return {
"import": False,
"status": "skip",
"reviewed": True,
"import_mode": "all",
"notes": notes,
"mattermost_channel": "",
"mattermost_team": "",
"messages": {},
}
def main() -> int:
export_path = Path(
sys.argv[1] if len(sys.argv) > 1 and not sys.argv[1].startswith("-") else DEFAULT_EXPORT
).expanduser().resolve()
preset_path = DEFAULT_PRESET
for i, arg in enumerate(sys.argv[1:], 1):
if arg == "--preset" and i < len(sys.argv) - 1:
preset_path = Path(sys.argv[i + 1]).expanduser().resolve()
if not export_path.is_dir():
print(f"Export not found: {export_path}", file=sys.stderr)
return 1
if not preset_path.is_file():
print(f"Preset not found: {preset_path}", file=sys.stderr)
return 1
preset = load_preset(preset_path)
skip_all = preset["skip_all"]
channels_json = export_path / "channels.json"
if not channels_json.is_file():
print(f"No channels.json in {export_path}", file=sys.stderr)
return 1
all_names = {c["name"] for c in json.loads(channels_json.read_text()) if c.get("name")}
for d in export_path.iterdir():
if d.is_dir() and any(d.glob("*.json")):
all_names.add(d.name)
manifest: dict = {
"version": 1,
"export_path": str(export_path),
"updated_at": datetime.now(tz=timezone.utc).isoformat(),
"global_notes": f"Preset skips from {preset_path.name}",
"channels": {},
"users": {},
}
if MANIFEST_PATH.is_file():
existing = json.loads(MANIFEST_PATH.read_text(encoding="utf-8"))
if isinstance(existing.get("users"), dict):
manifest["users"] = existing["users"]
for name, entry in (existing.get("channels") or {}).items():
if name not in skip_all and isinstance(entry, dict):
manifest["channels"][name] = entry
skipped = []
for name in sorted(skip_all):
if name in all_names or (export_path / name).is_dir():
tier = (
"tier-a"
if name in preset["tier_a"]
else "tier-b"
if name in preset["tier_b"]
else "other"
)
manifest["channels"][name] = channel_entry_skip(
f"Preset skip ({tier})"
)
skipped.append(name)
undecided = [
n
for n in sorted(all_names)
if n not in skip_all and n not in manifest["channels"]
]
MANIFEST_PATH.write_text(
json.dumps(manifest, indent=2, ensure_ascii=False) + "\n",
encoding="utf-8",
)
print(f"Wrote {MANIFEST_PATH}")
print(f" Skipped ({len(skipped)}): {', '.join('#' + n for n in skipped)}")
print(f" Still undecided ({len(undecided)}): {', '.join('#' + n for n in undecided)}")
print("\nSuggested review order:")
for n in preset["review_priority"]:
if n in undecided:
print(f" → #{n}")
for n in sorted(preset["review_later"]):
if n in undecided:
print(f" (later) #{n}")
return 0
if __name__ == "__main__":
raise SystemExit(main())