From 4e5c7da29875af4e0d90ab949af08cfe77155457 Mon Sep 17 00:00:00 2001 From: IMXEren <96839938+IMXEren@users.noreply.github.com> Date: Wed, 19 Mar 2025 23:19:06 +0530 Subject: [PATCH] Options Args --- src/parser.py | 76 ++++++++++++++++++++++++++++++++++++++++------ src/patches_gen.py | 2 +- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/parser.py b/src/parser.py index 8982b00..8affeab 100644 --- a/src/parser.py +++ b/src/parser.py @@ -1,8 +1,9 @@ """Revanced Parser.""" +import json from subprocess import PIPE, Popen from time import perf_counter -from typing import Self +from typing import Any, Self from loguru import logger @@ -22,7 +23,7 @@ class Parser(object): PATCHES_ARG = "-p" OUTPUT_ARG = "-o" KEYSTORE_ARG = "--keystore" - OPTIONS_ARG = "--legacy-options" + OPTIONS_ARG = "-O" def __init__(self: Self, patcher: Patches, config: RevancedConfig) -> None: self._PATCHES: list[str] = [] @@ -30,7 +31,7 @@ class Parser(object): self.patcher = patcher self.config = config - def include(self: Self, name: str) -> None: + def format_option(self: Self, opt: dict[str, Any]) -> str: """ The function `include` adds a given patch to the front of a list of patches. @@ -38,7 +39,35 @@ class Parser(object): ---------- name : str The `name` parameter is a string that represents the name of the patch to be included. + opt : dict[str, Any] + The `opt` parameter is a dictionary that represents the key-value pair of options + of the patch to be included. """ + pair: str = opt["key"] + if value := opt.get("value"): + if isinstance(value, bool): + pair += f'="{str(value).lower()}"' + else: + pair += f'="{value}"' + return pair + + def include(self: Self, name: str, options_list: list[dict[str, Any]]) -> None: + """ + The function `include` adds a given patch to the front of a list of patches. + + Parameters + ---------- + name : str + The `name` parameter is a string that represents the name of the patch to be included. + options_list : list[dict[str, Any]] + Then `options_list` parameter is a list of dictionary that represents the options for all patches. + """ + options_dict: dict[str, Any] = self.fetch_patch_options(name, options_list) + options = options_dict.get("options", []) + if options: + for opt in options: + pair = self.format_option(opt) + self._PATCHES[:0] = [self.OPTIONS_ARG, pair] self._PATCHES[:0] = ["-e", name] def exclude(self: Self, name: str) -> None: @@ -104,6 +133,21 @@ class Parser(object): if item == "-e": self._PATCHES[idx] = "-d" + def fetch_patch_options(self: Self, name: str, options_list: list[dict[str, Any]]) -> dict[str, Any]: + """The function `fetch_patch_options` finds patch options for the patch. + + Parameters + ---------- + name : str + Then `name` parameter is a string that represents the name of the patch. + options_list : list[dict[str, Any]] + Then `options_list` parameter is a list of dictionary that represents the options for all patches. + """ + return next( + filter(lambda obj: obj.get("patchName") == name, options_list), + {}, + ) + def include_exclude_patch( self: Self, app: APP, @@ -111,11 +155,20 @@ class Parser(object): patches_dict: dict[str, list[dict[str, str]]], ) -> None: """The function `include_exclude_patch` includes and excludes patches for a given app.""" + options_list: list[dict[str, Any]] = [{}] + try: + with self.config.temp_folder.joinpath(app.options_file).open() as file: + options_list = json.load(file) + # Not excepting on JSONDecodeError as it should error out if the file is not a valid JSON + except FileNotFoundError as e: + logger.warning(str(e)) + logger.debug("Setting options to empty list.") + if app.space_formatted: for patch in patches: normalized_patch = patch["name"].lower().replace(" ", "-") ( - self.include(patch["name"]) + self.include(patch["name"], options_list) if normalized_patch not in app.exclude_request else self.exclude( patch["name"], @@ -123,18 +176,25 @@ class Parser(object): ) for patch in patches_dict["universal_patch"]: normalized_patch = patch["name"].lower().replace(" ", "-") - self.include(patch["name"]) if normalized_patch in app.include_request else () + ( + self.include( + patch["name"], + options_list, + ) + if normalized_patch in app.include_request + else () + ) else: for patch in patches: ( - self.include(patch["name"]) + self.include(patch["name"], options_list) if patch["name"] not in app.exclude_request else self.exclude( patch["name"], ) ) for patch in patches_dict["universal_patch"]: - self.include(patch["name"]) if patch["name"] in app.include_request else () + self.include(patch["name"], options_list) if patch["name"] in app.include_request else () # noinspection IncorrectFormatting def patch_app( @@ -162,8 +222,6 @@ class Parser(object): app.get_output_file_name(), self.KEYSTORE_ARG, app.keystore_name, - self.OPTIONS_ARG, - app.options_file, ] args.append(exp) args[1::2] = map(self.config.temp_folder.joinpath, args[1::2]) diff --git a/src/patches_gen.py b/src/patches_gen.py index abd3e49..aedaec1 100644 --- a/src/patches_gen.py +++ b/src/patches_gen.py @@ -85,7 +85,7 @@ def convert_command_output_to_json( return result # Run the command - command = ["java", "-jar", jar_file_name, "list-patches", "-ipuv", patches_file] + command = ["java", "-jar", jar_file_name, "list-patches", "-ipuvo", patches_file] output = run_command_and_capture_output(command) parsed_data = parse_text_to_json(output)