Initial commit from Martins Github
This commit is contained in:
108
patch-ncm.py
Normal file
108
patch-ncm.py
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
patch-ncm.py — Inject P5G Marvis + P5G Radio pages into the NCM React bundle.
|
||||
|
||||
Reads from the clean .bak, applies all patches, writes the result.
|
||||
Safe to re-run (idempotent).
|
||||
"""
|
||||
|
||||
JS = "/etc/athonet/ems-frontend/advanced/assets/index-Cw8Irsq8.js"
|
||||
BAK = JS + ".bak"
|
||||
|
||||
with open(BAK, "r", encoding="utf-8") as f:
|
||||
src = f.read()
|
||||
|
||||
changed = False
|
||||
|
||||
# ── 1. Sidebar nav entry ───────────────────────────────────────────────────
|
||||
SIDEBAR_OLD = '!_o(ue.UPF,t)}]}]}'
|
||||
SIDEBAR_NEW = ('!_o(ue.UPF,t)}]},' # UPF entry closes; start custom entries
|
||||
'{value:"/marvis",label:"P5G Marvis",'
|
||||
'icon:a.jsx(ge.Magic,{}),disabled:false,'
|
||||
'subItems:['
|
||||
'{value:"/marvis/overview",label:"P5G Marvis Insights",disabled:false},'
|
||||
'{value:"/marvis/actions",label:"P5G Marvis Actions",disabled:false},'
|
||||
'{value:"/marvis/minis",label:"P5G Marvis Minis",disabled:false},'
|
||||
'{value:"/marvis/ai",label:"P5G Marvis AI",disabled:false}'
|
||||
']},' # close Marvis, comma before Radio
|
||||
'{value:"/radio",label:"P5G Radio",'
|
||||
'icon:a.jsx(ge.Magic,{}),disabled:false}'
|
||||
']}') # close outer items array + object
|
||||
|
||||
if SIDEBAR_OLD in src:
|
||||
src = src.replace(SIDEBAR_OLD, SIDEBAR_NEW, 1)
|
||||
print("Applied: sidebar entry")
|
||||
changed = True
|
||||
elif SIDEBAR_NEW.split(',icon')[0] in src:
|
||||
print("Skipped: sidebar entry already present")
|
||||
else:
|
||||
print("ERROR: sidebar anchor not found"); exit(1)
|
||||
|
||||
# ── 2. React Router route with iframe element ──────────────────────────────
|
||||
# Insert between G4t (UPF route object) and rht (Platform route object)
|
||||
# in the router children array — this is the unique anchor in the route config
|
||||
ROUTE_ANCHOR = 'G4t,rht'
|
||||
|
||||
# Wrap in Or({fullHeight:!0}) exactly like every other NF route — this gives the
|
||||
# NCM AppBar + left-navigation sidebar via G0, and a content area that properly
|
||||
# fills the remaining height. The iframe then uses height:"100%" to fill it.
|
||||
MARVIS_ROUTE = ('{path:"marvis",'
|
||||
'element:a.jsx(Or,{fullHeight:!0}),'
|
||||
'handle:vr({labelIntl:"P5G Marvis",icon:a.jsx(ge.Magic,{})}),'
|
||||
'children:['
|
||||
'{index:!0,element:a.jsx(ur,{to:"overview",replace:!0})},'
|
||||
'{path:"overview",element:a.jsx("iframe",{src:"/core/marvis/overview",style:{display:"block",width:"100%",height:"100%",border:"none"},title:"P5G Marvis Insights"})},'
|
||||
'{path:"actions",element:a.jsx("iframe",{src:"/core/marvis/actions",style:{display:"block",width:"100%",height:"100%",border:"none"},title:"P5G Marvis Actions"})},'
|
||||
'{path:"minis",element:a.jsx("iframe",{src:"/core/marvis/minis",style:{display:"block",width:"100%",height:"100%",border:"none"},title:"P5G Marvis Minis"})},'
|
||||
'{path:"ai",element:a.jsx("iframe",{src:"/core/marvis/",style:{display:"block",width:"100%",height:"100%",border:"none"},title:"P5G Marvis AI"})}'
|
||||
']}') # closed marvis route
|
||||
|
||||
RADIO_ROUTE = ('{path:"radio",'
|
||||
'element:a.jsx(Or,{fullHeight:!0}),'
|
||||
'handle:vr({labelIntl:"P5G Radio",icon:a.jsx(ge.Magic,{})}),'
|
||||
'children:['
|
||||
'{index:!0,element:a.jsx("iframe",{src:"/core/radio/",'
|
||||
'style:{display:"block",width:"100%",height:"100%",border:"none"},'
|
||||
'title:"P5G Radio"})}'
|
||||
']}')
|
||||
ROUTE_MARKER = 'path:"marvis"'
|
||||
|
||||
RADIO_MARKER = 'path:"radio"'
|
||||
|
||||
if ROUTE_ANCHOR in src and ROUTE_MARKER not in src:
|
||||
src = src.replace(ROUTE_ANCHOR, 'G4t,' + MARVIS_ROUTE + ',' + RADIO_ROUTE + ',rht', 1)
|
||||
print("Applied: marvis + radio routes with Or wrapper")
|
||||
changed = True
|
||||
elif ROUTE_MARKER in src:
|
||||
print("Skipped: marvis route already present")
|
||||
else:
|
||||
print("WARNING: route anchor G4t,rht not found — iframe routes not injected")
|
||||
|
||||
# ── Validate ───────────────────────────────────────────────────────────────
|
||||
# ── 3. Register /marvis in the BW permissions registry ────────────────────
|
||||
# BW is the route→permissions map. If a path is missing, the app throws
|
||||
# "Permissions for route /marvis are not managed". Tt=()=>!0 means no
|
||||
# specific permission required (same as profile and siteLoader routes).
|
||||
PERMS_OLD = '...QUe}'
|
||||
PERMS_NEW = '...QUe,"/marvis":Tt,"/marvis/overview":Tt,"/marvis/actions":Tt,"/marvis/minis":Tt,"/marvis/ai":Tt,"/radio":Tt}'
|
||||
|
||||
if PERMS_OLD in src and PERMS_NEW not in src:
|
||||
src = src.replace(PERMS_OLD, PERMS_NEW, 1)
|
||||
print("Applied: /marvis permissions entry")
|
||||
changed = True
|
||||
elif PERMS_NEW in src:
|
||||
print("Skipped: /marvis permissions entry already present")
|
||||
else:
|
||||
print("WARNING: BW permissions anchor not found — permissions not registered")
|
||||
|
||||
assert src.count('P5G Marvis') >= 1, "P5G Marvis not found after patch"
|
||||
assert src.count('P5G Radio') >= 1, "P5G Radio not found after patch"
|
||||
|
||||
if not changed:
|
||||
print("Nothing changed — already fully patched")
|
||||
exit(0)
|
||||
|
||||
with open(JS, "w", encoding="utf-8") as f:
|
||||
f.write(src)
|
||||
|
||||
print(f"Done — P5G Marvis: {src.count('P5G Marvis')} occurrences, P5G Radio: {src.count('P5G Radio')} occurrences")
|
||||
Reference in New Issue
Block a user