telecomkz_scraper/tools/rename_screen.py
Iliyas Kyrykbayev 5cb347a44b TelecomKz Analytics Mapper: audit fixes, real event keys, 32 mapped screens
Rebuilt the capture and mapping pipeline after an audit found the simulator's
data could not be trusted:

* Hotspot coordinates never matched the screenshots. Capture now scrolls the
  page over CDP and pastes each frame at the measured scrollY, so image pixels
  and DOM coordinates share one grid by construction.
* Metrics were synthesised (1200 + n*410) and presented as analytics. Numbers
  are now attached only when the catalog has a matching row; metrics.json
  carries a `source` label and the UI says "no data" instead of showing zeros.
* Event interception hooked a connector bridge that never fires. The app posts
  to api.amplitude.com using the legacy form-urlencoded v1 API; the hook now
  reads event_type off the wire. 36 keys are verified as `observed`.
* All device access moved into tools/telecom_cdp.py: dynamic WebView socket
  discovery (the PID was hardcoded), id-matched CDP, measured native geometry.
* Editor edits can now be saved to disk; API failures no longer report success
  from a stale result file; screenId is no longer interpolated into a shell.

Screens went from 7 (with fabricated markup) to 32, all verified: image height
equals map height, no out-of-bounds hotspots, no dead links.

The id_card screenshot has been manually redacted - it showed a national ID.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 18:16:46 +05:00

87 lines
2.9 KiB
Python

"""
Rename a captured screen: its id, its image files and its references in the app map.
Auto-generated ids (scr_*) are placeholders. Giving them meaningful names keeps the
map readable, and any hotspot pointing at the old id is repointed so no link breaks.
py tools/rename_screen.py scr_x_1 payments_auto --name "Мой автоплатеж" --category Финансы
"""
import argparse
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
import telecom_cdp as T
def rename(old_id, new_id, name=None, category=None):
T.validate_screen_id(old_id)
T.validate_screen_id(new_id)
app_map = T.load_app_map()
screen = next((s for s in app_map.get("screens", []) if s["id"] == old_id), None)
if screen is None:
raise ValueError("No screen with id " + old_id)
if any(s["id"] == new_id for s in app_map["screens"]):
raise ValueError("A screen named " + new_id + " already exists")
for suffix in ("_long.png", ".png", "_result.json"):
src = T.SCREENS_DIR / (old_id + suffix)
if src.exists():
src.replace(T.SCREENS_DIR / (new_id + suffix))
screen["id"] = new_id
screen["image"] = screen["image"].replace(old_id, new_id)
if name:
screen["name"] = name
if category:
screen["category"] = category
repointed = 0
for other in app_map["screens"]:
for hs in other.get("hotspots", []):
if hs.get("targetScreenId") == old_id:
hs["targetScreenId"] = new_id
repointed += 1
T.save_app_map(app_map)
result_path = T.SCREENS_DIR / (new_id + "_result.json")
if result_path.exists():
try:
data = json.loads(result_path.read_text(encoding="utf-8"))
data["screenId"] = new_id
data["imageUrl"] = data.get("imageUrl", "").replace(old_id, new_id)
if isinstance(data.get("screen"), dict):
data["screen"]["id"] = new_id
data["screen"]["image"] = data["screen"].get("image", "").replace(old_id, new_id)
result_path.write_text(
json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8"
)
except Exception as exc:
print("warning: could not rewrite result JSON: " + str(exc))
print(old_id + " -> " + new_id + " (links repointed: " + str(repointed) + ")")
def main():
parser = argparse.ArgumentParser(description="Rename a captured screen.")
parser.add_argument("old_id")
parser.add_argument("new_id")
parser.add_argument("--name", default=None)
parser.add_argument("--category", default=None)
args = parser.parse_args()
try:
rename(args.old_id, args.new_id, args.name, args.category)
except ValueError as exc:
print("Error: " + str(exc))
return 1
return 0
if __name__ == "__main__":
sys.exit(main())