diff --git a/patches/compress.py b/patches/compress.py index 5c92b84..5b74d60 100644 --- a/patches/compress.py +++ b/patches/compress.py @@ -1,4 +1,4 @@ -"""Remove unnecessary resources""" +"""Remove and compress resources""" # patch settings # priority, default: 0 @@ -8,6 +8,7 @@ priority = 0 ## bundled import os import shutil +import subprocess from typing import TypedDict ## installed @@ -15,17 +16,19 @@ from rich.progress import track ## custom from config import config, log, console - +from scripts.smali_parser import get_smali_lines # Patch + class PatchConfig_Compress(TypedDict): keep_dirs: list[str] -def apply(patch_config: PatchConfig_Compress) -> bool: - path = f"{config['folders']['decompiled']}/unknown" - items = os.listdir(path) +def remove_files(patch_config: PatchConfig_Compress): + path = f"{config['folders']['decompiled']}/unknown" + + items = os.listdir(path) for item in track( items, console=console, @@ -41,5 +44,77 @@ def apply(patch_config: PatchConfig_Compress) -> bool: shutil.rmtree(item_path) log.debug(f"[COMPRESS] removed directory: {item_path}") - log.debug(f"[COMPRESS] resources have been removed") + +def remove_debug_lines(): + for root, dirs, files in os.walk(f"{config['folders']['decompiled']}"): + if len(files) < 0: + continue + + for filename in files: + file_path = os.path.join(root, filename) + if os.path.isfile(file_path) and filename.endswith(".smali"): + file_content = get_smali_lines(file_path) + new_content = [] + for line in file_content: + if line.find(".line") >= 0: + continue + new_content.append(line) + + with open(file_path, "w", encoding="utf-8") as f: + f.writelines(new_content) + log.debug(f"[COMPRESS] removed debug lines from: {file_path}") + + +def compress_png(png_path: str): + try: + subprocess.run( + [ + "pngquant", + "--force", + "--ext", + ".png", + png_path, + ], + check=True, + capture_output=True, + ) + log.debug(f"[COMPRESS] compressed png: {png_path}") + except subprocess.CalledProcessError as e: + log.error( + f"error of running a command: %s :: %s", + " ".join( + [ + "pngquant", + "--force", + "--ext", + ".png", + png_path, + ] + ), + e.stderr, + exc_info=True, + ) + exit(1) + + +def compress_pngs(): + compressed = [] + for root, _, files in os.walk(f"{config['folders']['decompiled']}"): + if len(files) < 0: + continue + + for file in files: + if file.lower().endswith(".png"): + compress_png(f"{root}/{file}") + compressed.append(f"{root}/{file}") + + log.debug(f"[COMPRESS] {len(compressed)} pngs have been compressed") + + +def apply(patch_config: PatchConfig_Compress) -> bool: + + remove_files(patch_config) + remove_debug_lines() + compress_pngs() + return True diff --git a/scripts/utils.py b/scripts/utils.py index 12c6df9..045b6ed 100644 --- a/scripts/utils.py +++ b/scripts/utils.py @@ -39,7 +39,12 @@ def decompile_apk(apk: str): stderr=subprocess.PIPE, ) except subprocess.CalledProcessError as e: - log.fatal(f"error of running a command: %s", e.stderr, exc_info=True) + log.fatal( + f"error of running a command: %s :: %s", + f"java -jar {config['folders']['tools']}/apktool.jar d -f -o {config['folders']['decompiled']} {config['folders']['apks']}/{apk}", + e.stderr, + exc_info=True, + ) exit(1) @@ -63,13 +68,22 @@ def compile_apk(apk: str): stderr=subprocess.PIPE, ) except subprocess.CalledProcessError as e: - log.fatal(f"error of running a command: %s", e.stderr, exc_info=True) + log.fatal( + f"error of running a command: %s :: %s", + f"java -jar {config['folders']['tools']}/apktool.jar b -f -o {config['folders']['dist']}/{apk} {config['folders']['decompiled']}", + e.stderr, + exc_info=True, + ) exit(1) def sign_apk(apk: str): log.info(f"sign and align apk: `{apk}`") + command = "" try: + command = ( + f"zipalign -p 4 {config['folders']['dist']}/{apk} {config['folders']['dist']}/{apk.removesuffix(".apk")}-aligned.apk", + ) result = subprocess.run( f"zipalign -p 4 {config['folders']['dist']}/{apk} {config['folders']['dist']}/{apk.removesuffix(".apk")}-aligned.apk", shell=True, @@ -78,6 +92,10 @@ def sign_apk(apk: str): # stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, ) + + command = ( + f"apksigner sign --ks ./keystore.jks --out {config['folders']['dist']}/{apk.removesuffix(".apk")}-aligned-signed.apk {config['folders']['dist']}/{apk.removesuffix(".apk")}-aligned.apk", + ) result = subprocess.run( f"apksigner sign --ks ./keystore.jks --out {config['folders']['dist']}/{apk.removesuffix(".apk")}-aligned-signed.apk {config['folders']['dist']}/{apk.removesuffix(".apk")}-aligned.apk", shell=True, @@ -87,5 +105,5 @@ def sign_apk(apk: str): stderr=subprocess.PIPE, ) except subprocess.CalledProcessError as e: - log.fatal(f"error of running a command: %s", e.stderr, exc_info=True) + log.fatal(f"error of running a command: %s :: %s", command, e.stderr, exc_info=True) exit(1)