109 lines
3.3 KiB
Python
109 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Kleine Read-only-Hilfe zum Mining von OneXConsole app.asar.
|
|
Zieht gezielt RGB-Routen, Pipe-/Helper-Hinweise und Zonennamen raus.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import re
|
|
import struct
|
|
from pathlib import Path
|
|
|
|
DEFAULT_ASAR = Path.home() / "SuperX-goes-Arch/.cache/onexconsole/resources/app.asar"
|
|
|
|
PATTERNS = {
|
|
"route_prefixes": [
|
|
"/programhandle/rgb/setPreset/",
|
|
"/programhandle/rgb/setColor/",
|
|
"/programhandle/rgb/assignSetColor/",
|
|
"/programhandle/rgb/setOpen2/",
|
|
"/programhandle/rgb/assignSetOpen/",
|
|
],
|
|
"helpers": [
|
|
r"CompatLayerCT",
|
|
r"\\\\\.\\pipe\\CompatLayerCT",
|
|
],
|
|
"zones": [
|
|
r'rgbPartition_left_stick:\"[^\"]+\"',
|
|
r'rgbPartition_right_stick:\"[^\"]+\"',
|
|
r'rgbPartition_kb:\"[^\"]+\"',
|
|
r'rgbPartition_back:\"[^\"]+\"',
|
|
r'rgbPartition_v:\"[^\"]+\"',
|
|
r'rgbPlace0304:\"[^\"]+\"',
|
|
r'rgbPlace0304Enable:\"[^\"]+\"',
|
|
],
|
|
}
|
|
|
|
|
|
def load_asar_text(path: Path) -> dict[str, str]:
|
|
with path.open("rb") as f:
|
|
_, _, _, header_len = struct.unpack("<4I", f.read(16))
|
|
header = json.loads(f.read(header_len))
|
|
payload = f.read()
|
|
|
|
files: dict[str, str] = {}
|
|
|
|
def walk(prefix: str, node: dict) -> None:
|
|
if "files" in node:
|
|
for name, child in node["files"].items():
|
|
walk(f"{prefix}/{name}" if prefix else name, child)
|
|
return
|
|
if "offset" not in node or "size" not in node:
|
|
return
|
|
off = int(node["offset"])
|
|
size = int(node["size"])
|
|
if prefix.endswith((".js", ".json", ".html", ".txt")):
|
|
files[prefix] = payload[off : off + size].decode("utf-8", "replace")
|
|
|
|
walk("", header)
|
|
return files
|
|
|
|
|
|
def main() -> int:
|
|
if not DEFAULT_ASAR.exists():
|
|
print(f"app.asar nicht gefunden: {DEFAULT_ASAR}")
|
|
return 1
|
|
|
|
texts = load_asar_text(DEFAULT_ASAR)
|
|
interesting = [
|
|
p for p in texts if p == "background.js" or p.startswith("js/") or p == "package.json"
|
|
]
|
|
print(f"asar: {DEFAULT_ASAR}")
|
|
print(f"dateien gescannt: {len(interesting)}")
|
|
|
|
for section, pats in PATTERNS.items():
|
|
print(f"\n## {section}")
|
|
seen: set[str] = set()
|
|
for path in interesting:
|
|
text = texts[path]
|
|
if section == "route_prefixes":
|
|
for prefix in pats:
|
|
start = 0
|
|
while True:
|
|
idx = text.find(prefix, start)
|
|
if idx == -1:
|
|
break
|
|
snippet = text[max(0, idx - 80) : min(len(text), idx + 220)]
|
|
snippet = snippet.replace("\n", " ")
|
|
if snippet not in seen:
|
|
seen.add(snippet)
|
|
print(f"[{path}] {snippet}")
|
|
start = idx + len(prefix)
|
|
continue
|
|
for pat in pats:
|
|
for m in re.finditer(pat, text, re.I):
|
|
s = m.group(0)
|
|
if s in seen:
|
|
continue
|
|
seen.add(s)
|
|
print(f"[{path}] {s}")
|
|
if not seen:
|
|
print("(nichts gefunden)")
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|