Document Levkin Mattermost import and channel renames in prepare-export.
CI / skip-ci-check (pull_request) Successful in 8s
CI / secret-scan (pull_request) Failing after 6s
CI / python-ci (pull_request) Successful in 21s

Record the completed migration (channel map, mmetl/mmctl steps, caveats) and teach prepare-export to apply mattermost_channel renames plus user_emails for matching existing MM accounts.
This commit is contained in:
2026-07-10 13:36:09 -04:00
parent 4b034d19f6
commit 934b674995
4 changed files with 123 additions and 122 deletions
+36 -6
View File
@@ -99,8 +99,10 @@ def prepare_export(
channels_meta = []
manifest_channels = manifest.get("channels") or {}
email_map = manifest.get("user_emails") or {}
included_names: set[str] = set()
stats: dict[str, int] = {}
rename_map: dict[str, str] = {}
for ch in channels_meta:
name = ch.get("name")
@@ -110,25 +112,52 @@ def prepare_export(
if not channel_included(entry):
continue
included_names.add(name)
mm_name = (entry.get("mattermost_channel") or "").strip()
if mm_name and mm_name != name:
rename_map[name] = mm_name
# channels.json subset
filtered_meta = [c for c in channels_meta if c.get("name") in included_names]
# channels.json subset (optionally renamed for Mattermost)
filtered_meta = []
for c in channels_meta:
name = c.get("name")
if name not in included_names:
continue
out_ch = dict(c)
if name in rename_map:
out_ch["name"] = rename_map[name]
filtered_meta.append(out_ch)
(out_root / "channels.json").write_text(
json.dumps(filtered_meta, indent=2, ensure_ascii=False) + "\n",
encoding="utf-8",
)
# users.json — copy whole (mmetl needs user mapping)
# users.json — copy + inject emails so mmetl can match existing MM users
users_src = export.paths.users_json
if users_src.is_file():
shutil.copy2(users_src, out_root / "users.json")
users = load_json(users_src)
if isinstance(users, list) and email_map:
for u in users:
if not isinstance(u, dict):
continue
uid = u.get("id")
uname = u.get("name")
email = email_map.get(uid) or email_map.get(uname)
if email:
profile = dict(u.get("profile") or {})
profile["email"] = email
u["profile"] = profile
(out_root / "users.json").write_text(
json.dumps(users, indent=2, ensure_ascii=False) + "\n",
encoding="utf-8",
)
uploads_out = out_root / "__uploads"
uploads_src = export.paths.root / "__uploads"
for name in sorted(included_names):
entry = manifest_channels[name]
ch_out = out_root / name
out_name = rename_map.get(name, name)
ch_out = out_root / out_name
ch_out.mkdir(parents=True)
count = 0
for date in export.list_channel_date_files(name):
@@ -164,12 +193,13 @@ def prepare_export(
json.dumps(kept, indent=2, ensure_ascii=False) + "\n",
encoding="utf-8",
)
stats[name] = count
stats[out_name] = count
summary = {
"channels": len(stats),
"messages": sum(stats.values()),
"per_channel": stats,
"renames": rename_map,
}
(out_root / "prepare-export-summary.json").write_text(
json.dumps(summary, indent=2) + "\n",