refactor: single SETTINGS_SCHEMA in constants.py, sparse additionalSettings in source file, hydrate on export
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
"""Shared constants for Obtainium Emulation Pack scripts."""
|
||||
|
||||
from typing import Any, NamedTuple
|
||||
|
||||
SRC_FILE = "src/applications.json"
|
||||
PAGES_DIR = "pages"
|
||||
TABLE_FILE = "pages/table.md"
|
||||
@@ -11,12 +13,6 @@ VARIANTS = ("standard", "dual-screen")
|
||||
|
||||
GITHUB_NOREPLY_SUFFIX = "@users.noreply.github.com"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Obtainium source types and settings schema
|
||||
# Derived from Obtainium source code: lib/app_sources/*.dart
|
||||
# Reference: ~/code/Obtainium
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Valid overrideSource values (runtime type names from Obtainium)
|
||||
VALID_SOURCES = {
|
||||
"GitHub",
|
||||
@@ -71,107 +67,6 @@ SOURCE_HOST_MAP = {
|
||||
"sourceforge.net": "SourceForge",
|
||||
}
|
||||
|
||||
# Common additionalSettings keys valid for all source types
|
||||
COMMON_SETTINGS_KEYS = {
|
||||
"trackOnly",
|
||||
"versionExtractionRegEx",
|
||||
"matchGroupToUse",
|
||||
"versionDetection",
|
||||
"useVersionCodeAsOSVersion",
|
||||
"apkFilterRegEx",
|
||||
"invertAPKFilter",
|
||||
"autoApkFilterByArch",
|
||||
"appName",
|
||||
"appAuthor",
|
||||
"shizukuPretendToBeGooglePlay",
|
||||
"allowInsecure",
|
||||
"exemptFromBackgroundUpdates",
|
||||
"skipUpdateNotifications",
|
||||
"about",
|
||||
"refreshBeforeDownload",
|
||||
"releaseDateAsVersion",
|
||||
"includeZips",
|
||||
"zippedApkFilterRegEx",
|
||||
}
|
||||
|
||||
# Source-specific additionalSettings keys
|
||||
SOURCE_SPECIFIC_KEYS: dict[str, set[str]] = {
|
||||
"GitHub": {
|
||||
"includePrereleases",
|
||||
"fallbackToOlderReleases",
|
||||
"filterReleaseTitlesByRegEx",
|
||||
"filterReleaseNotesByRegEx",
|
||||
"verifyLatestTag",
|
||||
"sortMethodChoice",
|
||||
"useLatestAssetDateAsReleaseDate",
|
||||
"releaseTitleAsVersion",
|
||||
"github-creds",
|
||||
"GHReqPrefix",
|
||||
},
|
||||
"GitLab": {
|
||||
"fallbackToOlderReleases",
|
||||
"gitlab-creds",
|
||||
},
|
||||
"Codeberg": {
|
||||
# Inherits GitHub's settings
|
||||
"includePrereleases",
|
||||
"fallbackToOlderReleases",
|
||||
"filterReleaseTitlesByRegEx",
|
||||
"filterReleaseNotesByRegEx",
|
||||
"verifyLatestTag",
|
||||
"sortMethodChoice",
|
||||
"useLatestAssetDateAsReleaseDate",
|
||||
"releaseTitleAsVersion",
|
||||
},
|
||||
"FDroid": {
|
||||
"filterVersionsByRegEx",
|
||||
"trySelectingSuggestedVersionCode",
|
||||
"autoSelectHighestVersionCode",
|
||||
},
|
||||
"IzzyOnDroid": {
|
||||
# Inherits FDroid's settings
|
||||
"filterVersionsByRegEx",
|
||||
"trySelectingSuggestedVersionCode",
|
||||
"autoSelectHighestVersionCode",
|
||||
},
|
||||
"FDroidRepo": {
|
||||
"appIdOrName",
|
||||
"pickHighestVersionCode",
|
||||
"trySelectingSuggestedVersionCode",
|
||||
},
|
||||
"SourceHut": {
|
||||
"fallbackToOlderReleases",
|
||||
},
|
||||
"APKPure": {
|
||||
"fallbackToOlderReleases",
|
||||
"stayOneVersionBehind",
|
||||
"useFirstApkOfVersion",
|
||||
},
|
||||
"APKMirror": {
|
||||
"fallbackToOlderReleases",
|
||||
"filterReleaseTitlesByRegEx",
|
||||
},
|
||||
"Farsroid": {
|
||||
"useFirstApkOfVersion",
|
||||
},
|
||||
"HTML": {
|
||||
"intermediateLink",
|
||||
"customLinkFilterRegex",
|
||||
"filterByLinkText",
|
||||
"matchLinksOutsideATags",
|
||||
"skipSort",
|
||||
"reverseSort",
|
||||
"sortByLastLinkSegment",
|
||||
"versionExtractWholePage",
|
||||
"requestHeader",
|
||||
"defaultPseudoVersioningMethod",
|
||||
},
|
||||
"DirectAPKLink": {
|
||||
"requestHeader",
|
||||
"defaultPseudoVersioningMethod",
|
||||
},
|
||||
}
|
||||
|
||||
# Deprecated keys still accepted for backward compatibility.
|
||||
# Obtainium auto-migrates these on load (see appJSONCompatibilityModifiers
|
||||
# in lib/providers/source_provider.dart). New configs should use the
|
||||
@@ -182,13 +77,111 @@ DEPRECATED_SETTINGS_KEYS: dict[str, str] = {
|
||||
"sortByFileNamesNotLinks": "sortByLastLinkSegment",
|
||||
}
|
||||
|
||||
# Settings keys that contain regex patterns (should be validated)
|
||||
REGEX_SETTINGS_KEYS = {
|
||||
"apkFilterRegEx",
|
||||
"versionExtractionRegEx",
|
||||
"filterReleaseTitlesByRegEx",
|
||||
"filterReleaseNotesByRegEx",
|
||||
"customLinkFilterRegex",
|
||||
"filterVersionsByRegEx",
|
||||
"zippedApkFilterRegEx",
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Obtainium additionalSettings schema
|
||||
# Single source of truth for key metadata: default value, applicable sources,
|
||||
# whether the value is a regex pattern. Derived from Obtainium source code:
|
||||
# lib/app_sources/*.dart. Reference: ~/code/Obtainium
|
||||
#
|
||||
# Dict insertion order defines the canonical key ordering used by
|
||||
# normalize-json.py and export hydration.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
ALL_SOURCES = frozenset(VALID_SOURCES)
|
||||
|
||||
_GITHUB_LIKE = frozenset({"GitHub", "Codeberg"})
|
||||
|
||||
_DEFAULT_USER_AGENT_HEADER = [
|
||||
{"requestHeader": "User-Agent: Mozilla/5.0 (Linux; Android 10; K) "
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/114.0.0.0 Mobile Safari/537.36"}
|
||||
]
|
||||
|
||||
|
||||
class SettingDef(NamedTuple):
|
||||
default: Any
|
||||
sources: frozenset[str]
|
||||
is_regex: bool = False
|
||||
|
||||
|
||||
SETTINGS_SCHEMA: dict[str, SettingDef] = {
|
||||
# --- GitHub / Codeberg source-specific ---
|
||||
"includePrereleases": SettingDef(False, _GITHUB_LIKE),
|
||||
"fallbackToOlderReleases": SettingDef(True, frozenset({"GitHub", "Codeberg", "GitLab", "SourceHut", "APKPure", "APKMirror"})),
|
||||
"filterReleaseTitlesByRegEx": SettingDef("", frozenset({"GitHub", "Codeberg", "APKMirror"}), is_regex=True),
|
||||
"filterReleaseNotesByRegEx": SettingDef("", _GITHUB_LIKE, is_regex=True),
|
||||
"verifyLatestTag": SettingDef(False, _GITHUB_LIKE),
|
||||
"sortMethodChoice": SettingDef("date", _GITHUB_LIKE),
|
||||
"useLatestAssetDateAsReleaseDate": SettingDef(False, _GITHUB_LIKE),
|
||||
"releaseTitleAsVersion": SettingDef(False, _GITHUB_LIKE),
|
||||
"github-creds": SettingDef("", frozenset({"GitHub"})),
|
||||
"GHReqPrefix": SettingDef("", frozenset({"GitHub"})),
|
||||
|
||||
# --- GitLab source-specific ---
|
||||
"gitlab-creds": SettingDef("", frozenset({"GitLab"})),
|
||||
|
||||
# --- FDroid / IzzyOnDroid source-specific ---
|
||||
"filterVersionsByRegEx": SettingDef("", frozenset({"FDroid", "IzzyOnDroid"}), is_regex=True),
|
||||
"trySelectingSuggestedVersionCode": SettingDef(True, frozenset({"FDroid", "IzzyOnDroid", "FDroidRepo"})),
|
||||
"autoSelectHighestVersionCode": SettingDef(False, frozenset({"FDroid", "IzzyOnDroid"})),
|
||||
|
||||
# --- FDroidRepo source-specific ---
|
||||
"appIdOrName": SettingDef("", frozenset({"FDroidRepo"})),
|
||||
"pickHighestVersionCode": SettingDef(False, frozenset({"FDroidRepo"})),
|
||||
|
||||
# --- APKPure source-specific ---
|
||||
"stayOneVersionBehind": SettingDef(False, frozenset({"APKPure"})),
|
||||
"useFirstApkOfVersion": SettingDef(True, frozenset({"APKPure", "Farsroid"})),
|
||||
|
||||
# --- HTML source-specific ---
|
||||
"intermediateLink": SettingDef([], frozenset({"HTML"})),
|
||||
"customLinkFilterRegex": SettingDef("", frozenset({"HTML"}), is_regex=True),
|
||||
"filterByLinkText": SettingDef(False, frozenset({"HTML"})),
|
||||
"matchLinksOutsideATags": SettingDef(False, frozenset({"HTML"})),
|
||||
"skipSort": SettingDef(False, frozenset({"HTML"})),
|
||||
"reverseSort": SettingDef(False, frozenset({"HTML"})),
|
||||
"sortByLastLinkSegment": SettingDef(False, frozenset({"HTML"})),
|
||||
"versionExtractWholePage": SettingDef(False, frozenset({"HTML"})),
|
||||
"requestHeader": SettingDef(_DEFAULT_USER_AGENT_HEADER, frozenset({"HTML", "DirectAPKLink"})),
|
||||
"defaultPseudoVersioningMethod": SettingDef("partialAPKHash", frozenset({"HTML", "DirectAPKLink"})),
|
||||
|
||||
# --- Common keys (all sources) ---
|
||||
"trackOnly": SettingDef(False, ALL_SOURCES),
|
||||
"versionExtractionRegEx": SettingDef("", ALL_SOURCES, is_regex=True),
|
||||
"matchGroupToUse": SettingDef("", ALL_SOURCES),
|
||||
"versionDetection": SettingDef(True, ALL_SOURCES),
|
||||
"releaseDateAsVersion": SettingDef(False, ALL_SOURCES),
|
||||
"useVersionCodeAsOSVersion": SettingDef(False, ALL_SOURCES),
|
||||
"apkFilterRegEx": SettingDef("", ALL_SOURCES, is_regex=True),
|
||||
"invertAPKFilter": SettingDef(False, ALL_SOURCES),
|
||||
"autoApkFilterByArch": SettingDef(True, ALL_SOURCES),
|
||||
"appName": SettingDef("", ALL_SOURCES),
|
||||
"appAuthor": SettingDef("", ALL_SOURCES),
|
||||
"shizukuPretendToBeGooglePlay": SettingDef(False, ALL_SOURCES),
|
||||
"allowInsecure": SettingDef(False, ALL_SOURCES),
|
||||
"exemptFromBackgroundUpdates": SettingDef(False, ALL_SOURCES),
|
||||
"skipUpdateNotifications": SettingDef(False, ALL_SOURCES),
|
||||
"about": SettingDef("", ALL_SOURCES),
|
||||
"refreshBeforeDownload": SettingDef(False, ALL_SOURCES),
|
||||
"includeZips": SettingDef(False, ALL_SOURCES),
|
||||
"zippedApkFilterRegEx": SettingDef("", ALL_SOURCES, is_regex=True),
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Derived views - computed from SETTINGS_SCHEMA so there's one place to update
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
COMMON_SETTINGS_KEYS: set[str] = {
|
||||
key for key, s in SETTINGS_SCHEMA.items() if s.sources == ALL_SOURCES
|
||||
}
|
||||
|
||||
SOURCE_SPECIFIC_KEYS: dict[str, set[str]] = {}
|
||||
for _source in VALID_SOURCES:
|
||||
_keys = {key for key, s in SETTINGS_SCHEMA.items() if _source in s.sources and s.sources != ALL_SOURCES}
|
||||
if _keys:
|
||||
SOURCE_SPECIFIC_KEYS[_source] = _keys
|
||||
|
||||
REGEX_SETTINGS_KEYS: set[str] = {
|
||||
key for key, s in SETTINGS_SCHEMA.items() if s.is_regex
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user