#!/usr/bin/env python3 """Bind Hermes Telegram participant names to the current update's visible handle.""" from __future__ import annotations import argparse import ast import hashlib import json import os import tempfile from pathlib import Path PATCH_VERSION = "teleo-telegram-visible-handle-name-policy-v1" PATCH_MARKER = " # TELEO_TELEGRAM_VISIBLE_HANDLE_NAME_POLICY_V1\n" SOURCE_ANCHOR = " user_name=user.full_name if user else None,\n" REPLACEMENT = ''' # TELEO_TELEGRAM_VISIBLE_HANDLE_NAME_POLICY_V1 # The current Telegram update is authoritative for the visible # handle. The stable Telegram user_id continues to own session # isolation; profile full_name is only a fallback when no public # username exists on this update. user_name=( (user.username or "").strip().lstrip("@") if user and (user.username or "").strip() else user.full_name if user else None ), ''' def sha256_text(value: str) -> str: return hashlib.sha256(value.encode("utf-8")).hexdigest() def patch_source(source: str) -> tuple[str, bool]: if PATCH_MARKER in source: required = ( '(user.username or "").strip().lstrip("@")', "else user.full_name if user else None", "user_id=str(user.id) if user else None", ) missing = [item for item in required if item not in source] if missing: raise ValueError(f"installed Telegram name-policy marker is incomplete: {missing}") if SOURCE_ANCHOR in source: raise ValueError("installed Telegram name-policy marker still contains the stale full-name anchor") return source, False if source.count(SOURCE_ANCHOR) != 1: raise ValueError("Hermes Telegram sender construction changed; refusing an unreviewed name-policy patch") patched = source.replace(SOURCE_ANCHOR, REPLACEMENT, 1) ast.parse(patched) return patched, True def install(path: Path, *, check: bool) -> tuple[dict[str, str | bool], int]: source = path.read_text(encoding="utf-8") patched, changed = patch_source(source) before_sha = sha256_text(source) after_sha = sha256_text(patched) if check: return { "patch_version": PATCH_VERSION, "status": "patch_required" if changed else "installed", "target": str(path), "sha256": before_sha, }, 1 if changed else 0 if changed: mode = path.stat().st_mode & 0o777 with tempfile.NamedTemporaryFile( "w", encoding="utf-8", dir=path.parent, prefix=f".{path.name}.", delete=False ) as handle: handle.write(patched) temp_path = Path(handle.name) try: temp_path.chmod(mode) os.replace(temp_path, path) finally: temp_path.unlink(missing_ok=True) ast.parse(path.read_text(encoding="utf-8")) return { "patch_version": PATCH_VERSION, "status": "installed_now" if changed else "already_installed", "target": str(path), "before_sha256": before_sha, "after_sha256": after_sha, }, 0 def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("target", type=Path) parser.add_argument("--check", action="store_true") args = parser.parse_args() result, code = install(args.target, check=args.check) print(json.dumps(result, sort_keys=True)) return code if __name__ == "__main__": raise SystemExit(main())