Files
Obtainium-Emulation-Pack/scripts/normalize-json.py

142 lines
3.5 KiB
Python

#!/usr/bin/env python3
import json
import sys
from pathlib import Path
from typing import Any
from constants import SRC_FILE
# Canonical key order - matches the output of generate_app_entry() in add-app.py
KEY_ORDER = [
"id",
"url",
"author",
"name",
"preferredApkIndex",
"additionalSettings",
"categories",
"allowIdChange",
"overrideSource",
"meta",
]
# Canonical key order for additionalSettings - source-specific keys first,
# then common keys, grouped logically. Matches DEFAULT_ADDITIONAL_SETTINGS
# in add-app.py with source-specific keys prepended.
SETTINGS_KEY_ORDER = [
# GitHub/Codeberg source-specific
"includePrereleases",
"fallbackToOlderReleases",
"filterReleaseTitlesByRegEx",
"filterReleaseNotesByRegEx",
"verifyLatestTag",
"sortMethodChoice",
"useLatestAssetDateAsReleaseDate",
"releaseTitleAsVersion",
"github-creds",
"GHReqPrefix",
# HTML source-specific
"intermediateLink",
"customLinkFilterRegex",
"filterByLinkText",
"matchLinksOutsideATags",
"skipSort",
"reverseSort",
"sortByLastLinkSegment",
"versionExtractWholePage",
"requestHeader",
"defaultPseudoVersioningMethod",
# Common keys
"trackOnly",
"versionExtractionRegEx",
"matchGroupToUse",
"versionDetection",
"releaseDateAsVersion",
"useVersionCodeAsOSVersion",
"apkFilterRegEx",
"invertAPKFilter",
"autoApkFilterByArch",
"appName",
"appAuthor",
"shizukuPretendToBeGooglePlay",
"allowInsecure",
"exemptFromBackgroundUpdates",
"skipUpdateNotifications",
"about",
"refreshBeforeDownload",
"includeZips",
"zippedApkFilterRegEx",
]
# Fields to backfill with defaults when missing
DEFAULTS: dict[str, object] = {
"allowIdChange": False,
}
def _order_dict(d: dict[str, Any], key_order: list[str]) -> dict[str, Any]:
ordered: dict[str, Any] = {}
for key in key_order:
if key in d:
ordered[key] = d[key]
# Preserve any unexpected keys at the end (safety net)
for key in d:
if key not in ordered:
ordered[key] = d[key]
return ordered
def normalize_app(app: dict) -> dict:
for key, default in DEFAULTS.items():
if key not in app:
app[key] = default
# Normalize additionalSettings key order if it's a dict
settings = app.get("additionalSettings")
if isinstance(settings, dict):
app["additionalSettings"] = _order_dict(settings, SETTINGS_KEY_ORDER)
return _order_dict(app, KEY_ORDER)
def normalize(input_path: str) -> int:
path = Path(input_path)
if not path.exists():
print(f"Error: {path} not found.")
return 1
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
apps = data.get("apps", [])
if not apps:
print("No apps found in file.")
return 1
changes = 0
for i, app in enumerate(apps):
normalized = normalize_app(app)
# Check if anything changed (key order or new defaults)
if list(app.keys()) != list(normalized.keys()) or app != normalized:
changes += 1
apps[i] = normalized
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
f.write("\n")
if changes:
print(f"Normalized {changes} app(s) in {path}")
else:
print(f"All {len(apps)} apps already normalized")
return 0
if __name__ == "__main__":
input_file = sys.argv[1] if len(sys.argv) > 1 else SRC_FILE
sys.exit(normalize(input_file))