diff --git a/.env.example b/.env.example
index adef50c..c2b4b50 100644
--- a/.env.example
+++ b/.env.example
@@ -3,7 +3,6 @@ EXTRA_FILES=https://github.com/inotia00/VancedMicroG/releases/latest@VancedMicro
PATCH_APPS=youtube,youtube_revancify_red,youtube_revancify_blue,youtube_mmt,youtube_music,reddit
GLOBAL_CLI_DL=https://github.com/revanced/revanced-cli
GLOBAL_PATCHES_DL=https://github.com/revanced/revanced-patches
-GLOBAL_PATCHES_JSON_DL=https://api.revanced.app/v4/patches/list
#Example
EXISTING_DOWNLOADED_APKS=twitter
@@ -12,7 +11,6 @@ PERSONAL_ACCESS_TOKEN=ghp_asample_token
#YouTube:
YOUTUBE_CLI_DL=https://github.com/inotia00/revanced-cli
YOUTUBE_PATCHES_DL=https://github.com/YT-Advanced/ReX-patches
-YOUTUBE_PATCHES_JSON_DL=https://github.com/YT-Advanced/ReX-patches
YOUTUBE_EXCLUDE_PATCH=custom-branding-icon-revancify-blue,custom-branding-icon-revancify-red,custom-branding-icon-mmt,custom-branding-youtube-name,enable-debug-logging
#Example
@@ -24,7 +22,6 @@ YOUTUBE_REVANCIFY_RED_PACKAGE_NAME=com.google.android.youtube
YOUTUBE_REVANCIFY_RED_DL_SOURCE=https://www.apkmirror.com/apk/google-inc/youtube/
YOUTUBE_REVANCIFY_RED_CLI_DL=https://github.com/inotia00/revanced-cli
YOUTUBE_REVANCIFY_RED_PATCHES_DL=https://github.com/YT-Advanced/ReX-patches
-YOUTUBE_REVANCIFY_RED_PATCHES_JSON_DL=https://github.com/YT-Advanced/ReX-patches
YOUTUBE_REVANCIFY_RED_EXCLUDE_PATCH=custom-branding-icon-revancify-blue,custom-branding-icon-mmt,custom-branding-youtube-name,enable-debug-logging
#YouTube Revancify Blue:
@@ -32,7 +29,6 @@ YOUTUBE_REVANCIFY_BLUE_PACKAGE_NAME=com.google.android.youtube
YOUTUBE_REVANCIFY_BLUE_DL_SOURCE=https://www.apkmirror.com/apk/google-inc/youtube/
YOUTUBE_REVANCIFY_BLUE_CLI_DL=https://github.com/inotia00/revanced-cli
YOUTUBE_REVANCIFY_BLUE_PATCHES_DL=https://github.com/YT-Advanced/ReX-patches
-YOUTUBE_REVANCIFY_BLUE_PATCHES_JSON_DL=https://github.com/YT-Advanced/ReX-patches
YOUTUBE_REVANCIFY_BLUE_EXCLUDE_PATCH=custom-branding-icon-revancify-red,custom-branding-icon-mmt,custom-branding-youtube-name,enable-debug-logging
#YouTube MMT:
@@ -40,13 +36,11 @@ YOUTUBE_MMT_PACKAGE_NAME=com.google.android.youtube
YOUTUBE_MMT_DL_SOURCE=https://www.apkmirror.com/apk/google-inc/youtube/
YOUTUBE_MMT_CLI_DL=https://github.com/inotia00/revanced-cli
YOUTUBE_MMT_PATCHES_DL=https://github.com/YT-Advanced/ReX-patches
-YOUTUBE_MMT_PATCHES_JSON_DL=https://github.com/YT-Advanced/ReX-patches
YOUTUBE_MMT_EXCLUDE_PATCH=custom-branding-icon-revancify-blue,custom-branding-icon-revancify-red,custom-branding-youtube-name,enable-debug-logging
#YouTube Music:
YOUTUBE_MUSIC_CLI_DL=https://github.com/inotia00/revanced-cli
YOUTUBE_MUSIC_PATCHES_DL=https://github.com/YT-Advanced/ReX-patches
-YOUTUBE_MUSIC_PATCHES_JSON_DL=https://github.com/YT-Advanced/ReX-patches
YOUTUBE_MUSIC_EXCLUDE_PATCH=custom-branding-icon-mmt,custom-branding-icon-revancify-blue,custom-branding-icon-revancify-red,custom-branding-music-name,enable-compact-dialog,enable-debug-logging
#Example
@@ -55,11 +49,9 @@ YOUTUBE_MUSIC_VERSION=6.15.52
#Reddit
REDDIT_CLI_DL=https://github.com/inotia00/revanced-cli
REDDIT_PATCHES_DL=https://github.com/YT-Advanced/ReX-patches
-REDDIT_PATCHES_JSON_DL=https://github.com/YT-Advanced/ReX-patches
#Example
#Twitter
TWITTER_VERSION=latest
TWITTER_CLI_DL=local://cli.jar
TWITTER_PATCHES_DL=local://patches.jar
-TWITTER_PATCHES_JSON_DL=local://patches.json
diff --git a/.env.my b/.env.my
index 6f84692..d4bda96 100644
--- a/.env.my
+++ b/.env.my
@@ -6,13 +6,10 @@ GLOBAL_PATCHES_DL=https://github.com/revanced/revanced-patches/releases/latest
#YouTube:
YOUTUBE_PATCHES_DL=https://github.com/inotia00/revanced-patches/latest-prerelease
-YOUTUBE_PATCHES_JSON_DL=https://github.com/inotia00/revanced-patches/latest-prerelease
YOUTUBE_EXCLUDE_PATCH=custom-branding-icon-youtube,custom-branding-name-youtube,enable-debug-logging,hide-fullscreen-button
#YouTube Music:
YOUTUBE_MUSIC_PATCHES_DL=https://github.com/inotia00/revanced-patches/latest-prerelease
-YOUTUBE_MUSIC_PATCHES_JSON_DL=https://github.com/inotia00/revanced-patches/latest-prerelease
-
YOUTUBE_MUSIC_EXCLUDE_PATCH=custom-branding-icon-youtube-music,custom-branding-name-youtube-music,enable-compact-dialog,enable-debug-logging,enable-old-player-layout
YOUTUBE_MUSIC_VERSION=latest
@@ -22,27 +19,3 @@ REDDIT_EXCLUDE_PATCH=change-package-name
#Twitter:
TWITTER_PATCHES_DL=https://github.com/crimera/piko/releases/latest
-
-
-#Global:
-#EXTRA_FILES=https://github.com/ReVanced/GmsCore/releases/latest@Revanced-Microg.apk
-#PATCH_APPS=youtube,youtube_music,reddit,instagram
-#
-#YOUTUBE_EXCLUDE_PATCH=custom-branding
-#
-#FACEBOOK_VERSION=latest
-#YOUTUBE_MUSIC_VERSION=latest
-#REDDIT_VERSION=latest
-#TWITTER_VERSION=latest
-#INSTAGRAM_VERSION=latest
-#
-#
-#SOUNDCLOUD_DL_SOURCE=https://apkpure.net/-/com.soundcloud.android
-#SOUNDCLOUD_PACKAGE_NAME=com.soundcloud.android
-#
-#REDDIT_DL_SOURCE=https://apkpure.net/-/com.reddit.frontpage
-#REDDIT_PACKAGE_NAME=com.reddit.frontpage
-#
-#
-#TWITTER_DL_SOURCE=https://apkpure.net/-/com.twitter.android
-#TWITTER_PACKAGE_NAME=com.twitter.android
diff --git a/README.md b/README.md
index 2225626..7cf8a01 100644
--- a/README.md
+++ b/README.md
@@ -117,7 +117,6 @@ You can use any of the following methods to build.
| [GLOBAL_CLI_DL*](#global-resources) | DL for CLI to be used for patching apps. | [Revanced CLI](https://github.com/revanced/revanced-cli) |
| [GLOBAL_PATCHES_DL*](#global-resources) | DL for Patches to be used for patching apps. | [Revanced Patches](https://github.com/revanced/revanced-patches) |
| [GLOBAL_SPACE_FORMATTED_PATCHES*](#global-resources) | Whether patches are space formatted. | True |
-| [GLOBAL_PATCHES_JSON_DL*](#global-resources) | DL for Patches Json to be used for patching apps. | [Revanced Patches](https://github.com/revanced/revanced-patches) |
| [GLOBAL_KEYSTORE_FILE_NAME*](#global-keystore-file-name) | Key file to be used for signing apps | [Builder's own key](https://github.com/nikhilbadyal/docker-py-revanced/blob/main/apks/revanced.keystore) |
| [GLOBAL_OLD_KEY*](#global-keystore-file-name) | Whether key was generated with cli v4(new) or not |
[Builder's v3(old) own key](https://github.com/nikhilbadyal/docker-py-revanced/blob/main/apks/revanced.keystore) |
| [GLOBAL_OPTIONS_FILE*](#global-options-file) | Options file to be used | [Builder's default file](https://github.com/nikhilbadyal/docker-py-revanced/blob/main/apks/options.json) |
@@ -140,7 +139,6 @@ You can use any of the following methods to build.
|:------------------------------------------------------------|:--------------------------------------------------------------------------------------------:|:-------------------------------|
| [*APP_NAME*_CLI_DL](#global-resources) | DL for CLI to be used for patching **APP_NAME**. | GLOBAL_CLI_DL |
| [*APP_NAME*_PATCHES_DL](#global-resources) | DL for Patches to be used for patching **APP_NAME**. | GLOBAL_PATCHES_DL |
-| [*APP_NAME*_PATCHES_JSON_DL](#global-resources) | DL for Patches Json to be used for patching **APP_NAME**. | GLOBAL_PATCHES_JSON_DL |
| [*APP_NAME*_SPACE_FORMATTED_PATCHES](#global-resources) | Whether patches are space formatted. **APP_NAME**. | GLOBAL_SPACE_FORMATTED_PATCHES |
| [*APP_NAME*_KEYSTORE_FILE_NAME](#global-keystore-file-name) | Key file to be used for signing **APP_NAME**. | GLOBAL_KEYSTORE_FILE_NAME |
| [*APP_NAME*_OLD_KEY](#global-keystore-file-name) | Whether key used was generated with cli > v4(new)
**APP_NAME**.
| GLOBAL_OLK_KEY |
@@ -293,7 +291,6 @@ You can use any of the following methods to build.
```dotenv
GLOBAL_CLI_DL=https://github.com/revanced/revanced-cli
GLOBAL_PATCHES_DL=https://github.com/revanced/revanced-patches
- GLOBAL_PATCHES_JSON_DL=https://api.revanced.app/v4/patches/list
```
Resources downloaded from envs and will be used for patching for any **APP_NAME**.
Unless provided different resource for the individual app.
@@ -304,7 +301,6 @@ You can use any of the following methods to build.
```dotenv
YOUTUBE_CLI_DL=https://github.com/inotia00/revanced-cli
YOUTUBE_PATCHES_DL=https://github.com/inotia00/revanced-patches
- YOUTUBE_PATCHES_JSON_DL=https://api.revanced.app/v4/patches/list
```
With the config tool will try to patch YouTube with resources from inotia00 while other global resource will used
for patching other apps.
diff --git a/src/app.py b/src/app.py
index 48fdb12..78b4d37 100644
--- a/src/app.py
+++ b/src/app.py
@@ -32,7 +32,6 @@ class APP(object):
self.experiment = False
self.cli_dl = config.env.str(f"{app_name}_CLI_DL".upper(), config.global_cli_dl)
self.patches_dl = config.env.str(f"{app_name}_PATCHES_DL".upper(), config.global_patches_dl)
- self.patches_json_dl = config.env.str(f"{app_name}_PATCHES_JSON_DL".upper(), config.global_patches_json_dl)
self.exclude_request: list[str] = config.env.list(f"{app_name}_EXCLUDE_PATCH".upper(), [])
self.include_request: list[str] = config.env.list(f"{app_name}_INCLUDE_PATCH".upper(), [])
self.resource: dict[str, dict[str, str]] = {}
@@ -45,6 +44,7 @@ class APP(object):
self.download_source = config.env.str(f"{app_name}_DL_SOURCE".upper(), "")
self.package_name = package_name
self.old_key = config.env.bool(f"{app_name}_OLD_KEY".upper(), config.global_old_key)
+ self.patches: list[dict[Any, Any]] = []
self.space_formatted = config.env.bool(
f"{app_name}_SPACE_FORMATTED_PATCHES".upper(),
config.global_space_formatted,
@@ -149,7 +149,6 @@ class APP(object):
download_tasks = [
("cli", self.cli_dl, config, ".*jar"),
("patches", self.patches_dl, config, ".*rvp"),
- ("patches_json", self.patches_json_dl, config, ".*"),
]
# Using a ThreadPoolExecutor for parallelism
diff --git a/src/config.py b/src/config.py
index b584fe1..d43711b 100644
--- a/src/config.py
+++ b/src/config.py
@@ -5,7 +5,7 @@ from typing import Self
from environs import Env
-from src.utils import default_build, default_cli, default_patches, default_patches_json, resource_folder
+from src.utils import default_build, default_cli, default_patches, resource_folder
class RevancedConfig(object):
@@ -22,7 +22,6 @@ class RevancedConfig(object):
self.dry_run = env.bool("DRY_RUN", False)
self.global_cli_dl = env.str("GLOBAL_CLI_DL", default_cli)
self.global_patches_dl = env.str("GLOBAL_PATCHES_DL", default_patches)
- self.global_patches_json_dl = env.str("GLOBAL_PATCHES_JSON_DL", default_patches_json)
self.global_keystore_name = env.str("GLOBAL_KEYSTORE_FILE_NAME", "revanced.keystore")
self.global_options_file = env.str("GLOBAL_OPTIONS_FILE", "options.json")
self.global_archs_to_build = env.list("GLOBAL_ARCHS_TO_BUILD", [])
diff --git a/src/parser.py b/src/parser.py
index db63bca..908789a 100644
--- a/src/parser.py
+++ b/src/parser.py
@@ -84,11 +84,10 @@ class Parser(object):
"""
try:
name = name.lower().replace(" ", "-")
- patch_index = self._PATCHES.index(name)
indices = [i for i in range(len(self._PATCHES)) if self._PATCHES[i] == name]
for patch_index in indices:
if self._PATCHES[patch_index - 1] == "-e":
- self._PATCHES[patch_index - 1] = "-i"
+ self._PATCHES[patch_index - 1] = "-d"
else:
self._PATCHES[patch_index - 1] = "-e"
except ValueError:
@@ -99,8 +98,10 @@ class Parser(object):
def exclude_all_patches(self: Self) -> None:
"""The function `exclude_all_patches` exclude all the patches."""
for idx, item in enumerate(self._PATCHES):
- if item == "-i":
- self._PATCHES[idx] = "-e"
+ if idx == 0:
+ continue
+ if item == "-e":
+ self._PATCHES[idx] = "-d"
def include_exclude_patch(
self: Self,
@@ -193,6 +194,7 @@ class Parser(object):
excluded = set(possible_archs) - set(app.archs_to_build)
for arch in excluded:
args.extend(("--rip-lib", arch))
+ args.extend(("-f",))
start = perf_counter()
logger.debug(f"Sending request to revanced cli for building with args java {args}")
process = Popen(["java", *args], stdout=PIPE)
diff --git a/src/patches.py b/src/patches.py
index d7932de..da5a758 100644
--- a/src/patches.py
+++ b/src/patches.py
@@ -1,15 +1,14 @@
"""Revanced Patches."""
import contextlib
-import json
-from pathlib import Path
-from typing import Any, ClassVar, Self
+from typing import ClassVar, Self
from loguru import logger
from src.app import APP
from src.config import RevancedConfig
-from src.exceptions import AppNotFoundError, PatchesJsonLoadError
+from src.exceptions import AppNotFoundError
+from src.patches_gen import convert_command_output_to_json
class Patches(object):
@@ -125,22 +124,23 @@ class Patches(object):
The `app` parameter is of type `APP`. It represents an instance of the `APP` class.
"""
self.patches_dict[app.app_name] = []
- patch_loader = PatchLoader()
- patches_file = app.resource["patches_json"]["file_name"]
- patches = patch_loader.load_patches(f"{config.temp_folder}/{patches_file}")
+ app.patches = convert_command_output_to_json(
+ f"{config.temp_folder}/{app.resource["cli"]["file_name"]}",
+ f"{config.temp_folder}/{app.resource["patches"]["file_name"]}",
+ )
- for patch in patches:
+ for patch in app.patches:
if not patch["compatiblePackages"]:
p = {x: patch[x] for x in ["name", "description"]}
p["app"] = "universal"
p["version"] = "all"
self.patches_dict["universal_patch"].append(p)
else:
- for compatible_package, versions in patch["compatiblePackages"].items():
+ for compatible_package, version in [(x["name"], x["versions"]) for x in patch["compatiblePackages"]]:
if app.package_name == compatible_package:
- p = {x: patch[x] for x in ["name", "description", "use"]}
+ p = {x: patch[x] for x in ["name", "description"]}
p["app"] = compatible_package
- p["version"] = versions[-1] if versions else "all"
+ p["version"] = version[-1] if version else "all"
self.patches_dict[app.app_name].append(p)
app.no_of_patches = len(self.patches_dict[app.app_name])
@@ -199,28 +199,3 @@ class Patches(object):
app.app_version = recommended_version
app.experiment = experiment
return total_patches
-
-
-class PatchLoader(object):
- """Patch Loader."""
-
- @staticmethod
- def load_patches(file_name: str) -> Any:
- """The function `load_patches` loads patches from a file and returns them.
-
- Parameters
- ----------
- file_name : str
- The `file_name` parameter is a string that represents the name or path of the file from which
- the patches will be loaded.
-
- Returns
- -------
- the patches loaded from the file.
- """
- try:
- with Path(file_name).open() as f:
- return json.load(f)
- except FileNotFoundError as e:
- msg = "File not found"
- raise PatchesJsonLoadError(msg, file_name=file_name) from e
diff --git a/src/patches_gen.py b/src/patches_gen.py
new file mode 100644
index 0000000..abd3e49
--- /dev/null
+++ b/src/patches_gen.py
@@ -0,0 +1,104 @@
+"""Generate patches using cli."""
+
+import re
+import subprocess
+from pathlib import Path
+from typing import Any
+
+
+def convert_command_output_to_json(
+ jar_file_name: str,
+ patches_file: str,
+) -> list[dict[Any, Any]]:
+ """
+ Runs the ReVanced CLI command, processes the output, and saves it as a sorted JSON file.
+
+ Args:
+ jar_file_name (str): Name or path of the JAR file to run.
+ patches_file (str): The patches file name or path to pass to the command.
+ """
+
+ def run_command_and_capture_output(patches_command: list[str]) -> Any:
+ result = subprocess.run(patches_command, capture_output=True, text=True, check=True)
+ return result.stdout
+
+ def parse_text_to_json(text: str) -> list[dict[Any, Any]]:
+ # Split the data into individual sections based on "Name:"
+ sections = re.split(r"(?=Name:)", text)
+ result = []
+
+ for section in sections:
+ # Extract the name
+ name_match = re.search(r"Name: (.*?)\n", section)
+ name = name_match.group(1).strip() if name_match else None
+
+ # Extract the description
+ description_match = re.search(r"Description: (.*?)\n", section)
+ description = description_match.group(1).strip() if description_match else ""
+
+ # Extract the enabled state
+ enabled_match = re.search(r"Enabled: (true|false)", section, re.IGNORECASE)
+ enabled = enabled_match.group(1).lower() == "true" if enabled_match else False
+
+ # Extract compatible packages
+ compatible_packages = []
+ if "Compatible packages:" in section:
+ package_sections = re.split(r"\s*Package name: ", section.split("Compatible packages:")[1])
+ for package_section in package_sections[1:]: # Skip the initial split
+ package_name = package_section.split("\n")[0].strip()
+ versions_match = re.search(r"Compatible versions:\s*((?:\d+\.\d+\.\d+\s*)+)", package_section)
+ versions = versions_match.group(1).split() if versions_match else []
+ compatible_packages.append({"name": package_name, "versions": versions if versions else None})
+
+ # Extract options
+ options = []
+ if "Options:" in section:
+ options_section = section.split("Options:")[1]
+ option_matches = re.findall(
+ r"Title: (.*?)\n\s*Description: (.*?)\n\s*Required: (true|false)\n\s*Key: (.*?)\n\s*Default: (.*?)\n(?:\s*Possible values:\s*(.*?))?\s*Type: (.*?)\n", # noqa: E501
+ options_section,
+ re.DOTALL,
+ )
+ for match in option_matches:
+ option = {
+ "title": match[0].strip(),
+ "description": match[1].strip(),
+ "required": match[2].lower() == "true",
+ "key": match[3].strip(),
+ "default": match[4].strip(),
+ "possible_values": [v.strip() for v in match[5].split() if v.strip()] if match[5] else [],
+ "type": match[6].strip(),
+ }
+ options.append(option)
+
+ # Append the parsed data
+ result.append(
+ {
+ "name": name,
+ "description": description,
+ "compatiblePackages": compatible_packages if compatible_packages else None,
+ "use": enabled,
+ "options": options,
+ },
+ )
+
+ return result
+
+ # Run the command
+ command = ["java", "-jar", jar_file_name, "list-patches", "-ipuv", patches_file]
+ output = run_command_and_capture_output(command)
+
+ parsed_data = parse_text_to_json(output)
+
+ # Filter out invalid entries where "name" is None
+ parsed_data = [entry for entry in parsed_data if entry["name"] is not None]
+
+ # Sort the data by the "name" field
+ parsed_data.sort(key=lambda x: x["name"])
+
+ with Path("patches.json").open("w") as file:
+ import json
+
+ json.dump(parsed_data, file, indent=2)
+
+ return parsed_data
diff --git a/src/utils.py b/src/utils.py
index ff9b9dc..2f9a886 100644
--- a/src/utils.py
+++ b/src/utils.py
@@ -38,7 +38,6 @@ request_header = {
}
default_cli = "https://github.com/revanced/revanced-cli/releases/latest"
default_patches = "https://github.com/revanced/revanced-patches/releases/latest"
-default_patches_json = "https://api.revanced.app/v4/patches/list"
bs4_parser = "html.parser"
changelog_file = "changelog.md"
changelog_json_file = "changelog.json"
@@ -52,7 +51,6 @@ time_zone = "Asia/Kolkata"
app_version_key = "app_version"
patches_version_key = "patches_version"
cli_version_key = "cli_version"
-patches_json_version_key = "patches_json_version"
implement_method = "Please implement the method"
status_code_200 = 200
resource_folder = "apks"
@@ -267,7 +265,6 @@ def save_patch_info(app: "APP", updates_info: dict[str, Any]) -> dict[str, Any]:
app_version_key: app.app_version,
patches_version_key: app.resource["patches"]["version"],
cli_version_key: app.resource["cli"]["version"],
- patches_json_version_key: app.resource["patches_json"]["version"],
"ms_epoch_since_patched": datetime_to_ms_epoch(datetime.now(timezone(time_zone))),
"date_patched": datetime.now(timezone(time_zone)),
"app_dump": app.for_dump(),