Слияние с обновлённым main

This commit is contained in:
2025-09-14 20:26:24 +03:00
8 changed files with 335 additions and 81 deletions
-22
View File
@@ -1,22 +0,0 @@
"""Remove unnecessary files"""
priority = 0
from tqdm import tqdm
import os
import shutil
def apply(config: dict) -> bool:
for item in os.listdir("./decompiled/unknown/"):
item_path = os.path.join("./decompiled/unknown/", item)
if os.path.isfile(item_path):
os.remove(item_path)
if config.get("verbose", False):
tqdm.write(f'Удалён файл: {item_path}')
elif os.path.isdir(item_path):
if item not in config["keep_dirs"]:
shutil.rmtree(item_path)
if config.get("verbose", False):
tqdm.write(f'Удалена папка: {item_path}')
return True
+30
View File
@@ -0,0 +1,30 @@
# Compress
Патч удаляет ненужные ресурсы что-бы уменьшить размер АПК
## настройки (compress в config.json)
- remove_unknown_files: true/false - удаляет файлы из директории decompiled/unknown
- remove_unknown_files_keep_dirs: list[str] - оставляет указанные директории в decompiled/unknown
- remove_debug_lines: true/false - удаляет строки `.line n` из декомпилированных smali файлов использованные для дебага
- remove_AI_voiceover: true/false - заменяет ИИ озвучку маскота аниксы пустыми mp3 файлами
- compress_png_files: true/false - сжимает PNG в директории decompiled/res
- remove_drawable_files: true/false - удаляет неиспользованные drawable-* из директории decompiled/res
- remove_language_files: true/false - удаляет все языки кроме русского и английского
## efficiency
Проверено с версией 9.0 Beta 7
разница = оригинальный размер апк - патченный размер апк, не учитывая другие патчи
| Настройка | Размер файла | Разница | % |
| :----------- | :-------------------: | :-----------------: | :-: |
| None | 17092 bytes - 17.1 MB | - | - |
| Compress PNG | 17072 bytes - 17.1 MB | 20 bytes - 0.0 MB | 0.11% |
| Remove files | 17020 bytes - 17.0 MB | 72 bytes - 0.1 MB | 0.42% |
| Remove draws | 16940 bytes - 16.9 MB | 152 bytes - 0.2 MB | 0.89% |
| Remove lines | 16444 bytes - 16.4 MB | 648 bytes - 0.7 MB | 3.79% |
| Remove ai vo | 15812 bytes - 15.8 MB | 1280 bytes - 1.3 MB | 7.49% |
| Remove langs | 15764 bytes - 15.7 MB | 1328 bytes - 1.3 MB | 7.76% |
| Все включены | 13592 bytes - 13.6 MB | 3500 bytes - 4.8 MB | 20.5% |
+269
View File
@@ -0,0 +1,269 @@
"""Remove and compress resources"""
priority = -1
# imports
import os
import shutil
import subprocess
from tqdm import tqdm
from utils.smali_parser import get_smali_lines, save_smali_lines
# Patch
def remove_unknown_files(config):
path = "./decompiled/unknown"
items = os.listdir(path)
for item in items:
item_path = f"{path}/{item}"
if os.path.isfile(item_path):
os.remove(item_path)
if config.get("verbose", False):
tqdm.write(f"Удалён файл: {item_path}")
elif os.path.isdir(item_path):
if item not in config["remove_unknown_files_keep_dirs"]:
shutil.rmtree(item_path)
if config.get("verbose", False):
tqdm.write(f"Удалёна директория: {item_path}")
return True
def remove_debug_lines(config):
for root, _, files in os.walk("./decompiled"):
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)
save_smali_lines(file_path, new_content)
if config.get("verbose", False):
tqdm.write(f"Удалены дебаг линии из: {file_path}")
return True
def compress_png(config, png_path: str):
try:
assert subprocess.run(
[
"pngquant",
"--force",
"--ext",
".png",
"--quality=65-90",
png_path,
],
capture_output=True,
).returncode in [0, 99]
if config.get("verbose", False):
tqdm.write(f"Сжат файл PNG: {png_path}")
return True
except subprocess.CalledProcessError as e:
tqdm.write(f"Ошибка при сжатии {png_path}: {e}")
return False
def compress_png_files(config):
compressed = []
for root, _, files in os.walk("./decompiled"):
for file in files:
if file.lower().endswith(".png"):
compress_png(config, f"{root}/{file}")
compressed.append(f"{root}/{file}")
return len(compressed) > 0 and any(compressed)
def remove_AI_voiceover(config):
blank = "./patches/resources/blank.mp3"
path = "./decompiled/res/raw"
files = [
"reputation_1.mp3",
"reputation_2.mp3",
"reputation_3.mp3",
"sound_beta_1.mp3",
"sound_create_blog_1.mp3",
"sound_create_blog_2.mp3",
"sound_create_blog_3.mp3",
"sound_create_blog_4.mp3",
"sound_create_blog_5.mp3",
"sound_create_blog_6.mp3",
"sound_create_blog_reputation_1.mp3",
"sound_create_blog_reputation_2.mp3",
"sound_create_blog_reputation_3.mp3",
"sound_create_blog_reputation_4.mp3",
"sound_create_blog_reputation_5.mp3",
"sound_create_blog_reputation_6.mp3",
]
for file in files:
if os.path.exists(f"{path}/{file}"):
os.remove(f"{path}/{file}")
shutil.copyfile(blank, f"{path}/{file}")
if config.get("verbose", False):
tqdm.write(f"Файл mp3 был заменён на пустой: {path}/{file}")
return True
def remove_language_files(config):
path = "./patches/res"
folders = [
"values-af",
"values-am",
"values-ar",
"values-as",
"values-az",
"values-b+es+419",
"values-b+sr+Latn",
"values-be",
"values-bg",
"values-bn",
"values-bs",
"values-ca",
"values-cs",
"values-da",
"values-de",
"values-el",
"values-en-rAU",
"values-en-rCA",
"values-en-rGB",
"values-en-rIN",
"values-en-rXC",
"values-es",
"values-es-rGT",
"values-es-rUS",
"values-et",
"values-eu",
"values-fa",
"values-fi",
"values-fr",
"values-fr-rCA",
"values-gl",
"values-gu",
"values-hi",
"values-hr",
"values-hu",
"values-hy",
"values-in",
"values-is",
"values-it",
"values-iw",
"values-ja",
"values-ka",
"values-kk",
"values-km",
"values-kn",
"values-ko",
"values-ky",
"values-lo",
"values-lt",
"values-lv",
"values-mk",
"values-ml",
"values-mn",
"values-mr",
"values-ms",
"values-my",
"values-nb",
"values-ne",
"values-nl",
"values-or",
"values-pa",
"values-pl",
"values-pt",
"values-pt-rBR",
"values-pt-rPT",
"values-ro",
"values-si",
"values-sk",
"values-sl",
"values-sq",
"values-sr",
"values-sv",
"values-sw",
"values-ta",
"values-te",
"values-th",
"values-tl",
"values-tr",
"values-uk",
"values-ur",
"values-uz",
"values-vi",
"values-zh",
"values-zh-rCN",
"values-zh-rHK",
"values-zh-rTW",
"values-zu",
"values-watch",
]
for folder in folders:
if os.path.exists(f"{path}/{folder}"):
shutil.rmtree(f"{path}/{folder}")
if config.get("verbose", False):
tqdm.write(f"Удалена директория: {path}/{folder}")
return True
def remove_drawable_files(config):
path = "./patches/res"
folders = [
"drawable-en-hdpi",
"drawable-en-ldpi",
"drawable-en-mdpi",
"drawable-en-xhdpi",
"drawable-en-xxhdpi",
"drawable-en-xxxhdpi",
"drawable-ldrtl-hdpi",
"drawable-ldrtl-mdpi",
"drawable-ldrtl-xhdpi",
"drawable-ldrtl-xxhdpi",
"drawable-ldrtl-xxxhdpi",
"drawable-tr-anydpi",
"drawable-tr-hdpi",
"drawable-tr-ldpi",
"drawable-tr-mdpi",
"drawable-tr-xhdpi",
"drawable-tr-xxhdpi",
"drawable-tr-xxxhdpi",
"drawable-watch",
"layout-watch",
]
for folder in folders:
if os.path.exists(f"{path}/{folder}"):
shutil.rmtree(f"{path}/{folder}")
if config.get("verbose", False):
tqdm.write(f"Удалена директория: {path}/{folder}")
return True
def apply(config) -> bool:
if config["remove_unknown_files"]:
tqdm.write(f"Удаление неизвестных файлов...")
remove_unknown_files(config)
if config["remove_drawable_files"]:
tqdm.write(f"Удаление директорий drawable-xx...")
remove_drawable_files(config)
if config["compress_png_files"]:
tqdm.write(f"Сжатие PNG файлов...")
compress_png_files(config)
if config["remove_language_files"]:
tqdm.write(f"Удаление языков...")
remove_language_files(config)
if config["remove_AI_voiceover"]:
tqdm.write(f"Удаление ИИ озвучки...")
remove_AI_voiceover(config)
if config["remove_debug_lines"]:
tqdm.write(f"Удаление дебаг линий...")
remove_debug_lines(config)
return True
-36
View File
@@ -1,36 +0,0 @@
"""Compress PNGs"""
priority = -1
from tqdm import tqdm
import os
import subprocess
def compress_pngs(root_dir: str, verbose: bool = False):
compressed_files = []
for dirpath, _, filenames in os.walk(root_dir):
for filename in filenames:
if filename.lower().endswith(".png"):
filepath = os.path.join(dirpath, filename)
if verbose: tqdm.write(f"Сжимаю: {filepath}")
try:
assert subprocess.run(
[
"pngquant",
"--force",
"--ext",
".png",
"--quality=65-90",
filepath,
],
capture_output=True,
).returncode in [0, 99]
compressed_files.append(filepath)
except subprocess.CalledProcessError as e:
tqdm.write(f"Ошибка при сжатии {filepath}: {e}")
return compressed_files
def apply(config: dict) -> bool:
files = compress_pngs("./decompiled", config.get("verbose", False))
return len(files) > 0 and any(files)
Binary file not shown.